mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa8089556a | ||
|
|
f572a5c300 | ||
|
|
dcd11e6c4b | ||
|
|
3f1a920888 |
@@ -51,6 +51,13 @@
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
|
||||
<data android:scheme="bikecontrol" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
|
||||
@@ -20,7 +20,5 @@
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
PODS:
|
||||
- app_links (6.4.1):
|
||||
- Flutter
|
||||
- AppAuth (2.0.0):
|
||||
- AppAuth/Core (= 2.0.0)
|
||||
- AppAuth/ExternalUserAgent (= 2.0.0)
|
||||
- AppAuth/Core (2.0.0)
|
||||
- AppAuth/ExternalUserAgent (2.0.0):
|
||||
- AppAuth/Core
|
||||
- AppCheckCore (11.2.0):
|
||||
- GoogleUtilities/Environment (~> 8.0)
|
||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- audio_session (0.0.1):
|
||||
- Flutter
|
||||
- bluetooth_low_energy_darwin (0.0.1):
|
||||
@@ -16,6 +28,33 @@ PODS:
|
||||
- Flutter
|
||||
- gamepads_ios (0.1.1):
|
||||
- Flutter
|
||||
- google_sign_in_ios (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- GoogleSignIn (~> 9.0)
|
||||
- GTMSessionFetcher (>= 3.4.0)
|
||||
- GoogleSignIn (9.1.0):
|
||||
- AppAuth (~> 2.0)
|
||||
- AppCheckCore (~> 11.0)
|
||||
- GTMAppAuth (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 3.3)
|
||||
- GoogleUtilities/Environment (8.1.0):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Logger (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (8.1.0)
|
||||
- GoogleUtilities/UserDefaults (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GTMAppAuth (5.0.0):
|
||||
- AppAuth/Core (~> 2.0)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3)
|
||||
- GTMSessionFetcher (3.5.0):
|
||||
- GTMSessionFetcher/Full (= 3.5.0)
|
||||
- GTMSessionFetcher/Core (3.5.0)
|
||||
- GTMSessionFetcher/Full (3.5.0):
|
||||
- GTMSessionFetcher/Core
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- in_app_purchase_storekit (0.0.1):
|
||||
@@ -38,6 +77,7 @@ PODS:
|
||||
- Flutter
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- PromisesObjC (2.4.0)
|
||||
- purchases_flutter (9.10.6):
|
||||
- Flutter
|
||||
- PurchasesHybridCommon (= 17.27.1)
|
||||
@@ -59,6 +99,8 @@ PODS:
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sign_in_with_apple (0.0.1):
|
||||
- Flutter
|
||||
- universal_ble (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -68,6 +110,7 @@ PODS:
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
||||
- bluetooth_low_energy_darwin (from `.symlinks/plugins/bluetooth_low_energy_darwin/darwin`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
@@ -76,6 +119,7 @@ DEPENDENCIES:
|
||||
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
||||
- flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`)
|
||||
- gamepads_ios (from `.symlinks/plugins/gamepads_ios/ios`)
|
||||
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||
@@ -91,18 +135,28 @@ DEPENDENCIES:
|
||||
- restart_app (from `.symlinks/plugins/restart_app/ios`)
|
||||
- sensors_plus (from `.symlinks/plugins/sensors_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||
- universal_ble (from `.symlinks/plugins/universal_ble/darwin`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- AppAuth
|
||||
- AppCheckCore
|
||||
- GoogleSignIn
|
||||
- GoogleUtilities
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
- PromisesObjC
|
||||
- PurchasesHybridCommon
|
||||
- PurchasesHybridCommonUI
|
||||
- RevenueCat
|
||||
- RevenueCatUI
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: ".symlinks/plugins/app_links/ios"
|
||||
audio_session:
|
||||
:path: ".symlinks/plugins/audio_session/ios"
|
||||
bluetooth_low_energy_darwin:
|
||||
@@ -119,6 +173,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_volume_controller/ios"
|
||||
gamepads_ios:
|
||||
:path: ".symlinks/plugins/gamepads_ios/ios"
|
||||
google_sign_in_ios:
|
||||
:path: ".symlinks/plugins/google_sign_in_ios/darwin"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
in_app_purchase_storekit:
|
||||
@@ -149,6 +205,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/sensors_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
sign_in_with_apple:
|
||||
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||
universal_ble:
|
||||
:path: ".symlinks/plugins/universal_ble/darwin"
|
||||
url_launcher_ios:
|
||||
@@ -157,6 +215,9 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: 585674be3c6661708e6cd794ab4f39fb9d8356f9
|
||||
AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063
|
||||
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
|
||||
audio_session: 19e9480dbdd4e5f6c4543826b2e8b0e4ab6145fe
|
||||
bluetooth_low_energy_darwin: 50bc79258e60586e4c4bed5948bd31d925f37fac
|
||||
device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
|
||||
@@ -165,6 +226,11 @@ SPEC CHECKSUMS:
|
||||
flutter_secure_storage_darwin: 557817588b80e60213cbecb573c45c76b788018d
|
||||
flutter_volume_controller: e4d5832f08008180f76e30faf671ffd5a425e529
|
||||
gamepads_ios: 1d2930c7a4450a9a1b57444ebf305a6a6cbeea0b
|
||||
google_sign_in_ios: 7336a3372ea93ea56a21e126a0055ffca3723601
|
||||
GoogleSignIn: fcee2257188d5eda57a5e2b6a715550ffff9206d
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
GTMAppAuth: 217a876b249c3c585a54fd6f73e6b58c4f5c4238
|
||||
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
||||
image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b
|
||||
in_app_purchase_storekit: 2342c0a5da86593124d08dd13d920f39a52b273a
|
||||
in_app_review: 436034b18594851a7328d7f1c2ed5ec235b79cfc
|
||||
@@ -175,6 +241,7 @@ SPEC CHECKSUMS:
|
||||
nsd_ios: 8c37babdc6538e3350dbed3a52674d2edde98173
|
||||
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
purchases_flutter: b3c0792197f69cd7af4c2449b71df6ac6378aace
|
||||
purchases_ui_flutter: caae6d62ea23c6fe964992a28353211cc74b244a
|
||||
PurchasesHybridCommon: 027f03312519c51056457eb2e4f7ee1c91b61b8f
|
||||
@@ -184,6 +251,7 @@ SPEC CHECKSUMS:
|
||||
RevenueCatUI: ac7492873928e9e7f297e5e27a7c4f23f9008326
|
||||
sensors_plus: 7229095999f30740798f0eeef5cd120357a8f4f2
|
||||
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
|
||||
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
||||
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa
|
||||
wakelock_plus: 76957ab028e12bfa4e66813c99e46637f367fc7e
|
||||
|
||||
@@ -280,14 +280,10 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
@@ -376,14 +372,10 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
|
||||
@@ -22,6 +22,19 @@
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.googleusercontent.apps.709945926587-0iierajthibf4vhqf85fc7bbpgbdgua2</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GIDClientID</key>
|
||||
<string>709945926587-0iierajthibf4vhqf85fc7bbpgbdgua2.apps.googleusercontent.com</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array/>
|
||||
</dict>
|
||||
|
||||
131
lib/pages/login.dart
Normal file
131
lib/pages/login.dart
Normal file
@@ -0,0 +1,131 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:bike_control/utils/requirements/windows.dart';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:google_sign_in/google_sign_in.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:sign_in_button/sign_in_button.dart';
|
||||
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
|
||||
import '../utils/core.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({super.key});
|
||||
|
||||
@override
|
||||
State<LoginPage> createState() => _LoginPageState();
|
||||
}
|
||||
|
||||
class _LoginPageState extends State<LoginPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(32.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Please sign in to continue'),
|
||||
const SizedBox(height: 16),
|
||||
SignInButton(
|
||||
Buttons.google,
|
||||
onPressed: _nativeGoogleSignIn,
|
||||
),
|
||||
SignInButton(
|
||||
Buttons.apple,
|
||||
onPressed: _signInWithApple,
|
||||
),
|
||||
Button.secondary(
|
||||
child: Text('Logout'),
|
||||
onPressed: () {
|
||||
core.supabase.auth.signOut();
|
||||
},
|
||||
),
|
||||
if (kDebugMode && Platform.isWindows)
|
||||
Button.secondary(
|
||||
child: Text("Register"),
|
||||
onPressed: () {
|
||||
WindowsProtocolHandler().register("bikecontrol");
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<AuthResponse?> _nativeGoogleSignIn() async {
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
/// Web Client ID that you registered with Google Cloud.
|
||||
const webClientId = '709945926587-bgk7j9qc86t7nuemu100ngvl9c7irv9k.apps.googleusercontent.com';
|
||||
|
||||
/// iOS Client ID that you registered with Google Cloud.
|
||||
const iosClientId = '709945926587-0iierajthibf4vhqf85fc7bbpgbdgua2.apps.googleusercontent.com';
|
||||
final scopes = ['email'];
|
||||
final googleSignIn = GoogleSignIn.instance;
|
||||
await googleSignIn.initialize(
|
||||
serverClientId: webClientId,
|
||||
clientId: iosClientId,
|
||||
);
|
||||
GoogleSignInAccount? googleUser = await googleSignIn.attemptLightweightAuthentication(reportAllExceptions: true);
|
||||
googleUser ??= await googleSignIn.authenticate();
|
||||
|
||||
/// Authorization is required to obtain the access token with the appropriate scopes for Supabase authentication,
|
||||
/// while also granting permission to access user information.
|
||||
final authorization =
|
||||
await googleUser.authorizationClient.authorizationForScopes(scopes) ??
|
||||
await googleUser.authorizationClient.authorizeScopes(scopes);
|
||||
final idToken = googleUser.authentication.idToken;
|
||||
if (idToken == null) {
|
||||
throw AuthException('No ID Token found.');
|
||||
}
|
||||
final response = await core.supabase.auth.signInWithIdToken(
|
||||
provider: OAuthProvider.google,
|
||||
idToken: idToken,
|
||||
accessToken: authorization.accessToken,
|
||||
);
|
||||
return response;
|
||||
} else {
|
||||
await core.supabase.auth.signInWithOAuth(
|
||||
OAuthProvider.google,
|
||||
redirectTo: kIsWeb ? null : 'bikecontrol://login/',
|
||||
authScreenLaunchMode: kIsWeb
|
||||
? LaunchMode.platformDefault
|
||||
: LaunchMode.externalApplication, // Launch the auth screen in a new webview on mobile.
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs Apple sign in on iOS or macOS
|
||||
Future<AuthResponse?> _signInWithApple() async {
|
||||
if (Platform.isIOS || Platform.isMacOS) {
|
||||
final rawNonce = core.supabase.auth.generateRawNonce();
|
||||
final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
|
||||
|
||||
final credential = await SignInWithApple.getAppleIDCredential(
|
||||
scopes: [AppleIDAuthorizationScopes.email],
|
||||
nonce: hashedNonce,
|
||||
);
|
||||
final idToken = credential.identityToken;
|
||||
if (idToken == null) {
|
||||
throw const AuthException('Could not find ID Token from generated credential.');
|
||||
}
|
||||
final authResponse = await core.supabase.auth.signInWithIdToken(
|
||||
provider: OAuthProvider.apple,
|
||||
idToken: idToken,
|
||||
nonce: rawNonce,
|
||||
);
|
||||
return authResponse;
|
||||
} else {
|
||||
await core.supabase.auth.signInWithOAuth(
|
||||
OAuthProvider.apple,
|
||||
redirectTo: kIsWeb ? null : 'bikecontrol://login/',
|
||||
authScreenLaunchMode: kIsWeb ? LaunchMode.platformDefault : LaunchMode.externalApplication,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:prop/prop.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:universal_ble/universal_ble.dart';
|
||||
|
||||
import '../bluetooth/connection.dart';
|
||||
@@ -39,6 +40,7 @@ class Core {
|
||||
final settings = Settings();
|
||||
final connection = Connection();
|
||||
|
||||
late final supabase = Supabase.instance.client;
|
||||
late final whooshLink = WhooshLink();
|
||||
late final zwiftEmulator = ZwiftEmulator();
|
||||
late final zwiftMdnsEmulator = FtmsMdnsEmulator();
|
||||
|
||||
@@ -10,9 +10,11 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:prop/prop.dart' as zp;
|
||||
import 'package:prop/prop.dart' hide LogLevel;
|
||||
import 'package:purchases_flutter/purchases_flutter.dart';
|
||||
import 'package:purchases_ui_flutter/purchases_ui_flutter.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:version/version.dart';
|
||||
|
||||
/// RevenueCat-based IAP service for iOS, macOS, and Android
|
||||
@@ -39,6 +41,8 @@ class RevenueCatService {
|
||||
int? _dailyCommandCount;
|
||||
StreamSubscription<CustomerInfo>? _customerInfoSubscription;
|
||||
|
||||
late final StreamSubscription<AuthState> _authSubscription;
|
||||
|
||||
RevenueCatService(
|
||||
this._prefs, {
|
||||
required this.isPurchasedNotifier,
|
||||
@@ -120,6 +124,34 @@ class RevenueCatService {
|
||||
if (!isTrialExpired && Platform.isAndroid) {
|
||||
setDailyCommandLimit(80);
|
||||
}
|
||||
|
||||
_authSubscription = core.supabase.auth.onAuthStateChange.listen((data) {
|
||||
final AuthChangeEvent event = data.event;
|
||||
final Session? session = data.session;
|
||||
|
||||
Logger.info('event: $event, session: ${session?.user.id} via ${session?.user.email}');
|
||||
|
||||
switch (event) {
|
||||
case AuthChangeEvent.initialSession:
|
||||
setAttributes();
|
||||
case AuthChangeEvent.signedIn:
|
||||
setAttributes();
|
||||
// handle signed in
|
||||
case AuthChangeEvent.signedOut:
|
||||
setAttributes();
|
||||
// handle signed out
|
||||
case AuthChangeEvent.passwordRecovery:
|
||||
// handle password recovery
|
||||
case AuthChangeEvent.tokenRefreshed:
|
||||
// handle token refreshed
|
||||
case AuthChangeEvent.userUpdated:
|
||||
// handle user updated
|
||||
case AuthChangeEvent.userDeleted:
|
||||
// handle user deleted
|
||||
case AuthChangeEvent.mfaChallengeVerified:
|
||||
// handle mfa challenge verified
|
||||
}
|
||||
});
|
||||
} catch (e, s) {
|
||||
recordError(e, s, context: 'Initializing RevenueCat Service');
|
||||
core.connection.signalNotification(
|
||||
@@ -370,8 +402,11 @@ class RevenueCatService {
|
||||
}
|
||||
|
||||
Future<void> setAttributes() async {
|
||||
final Session? session = core.supabase.auth.currentSession;
|
||||
|
||||
// attributes are fully anonymous
|
||||
await Purchases.setAttributes({
|
||||
if (session?.user.id != null) "bikecontrol_user": session!.user.id,
|
||||
"bikecontrol_trainer": core.settings.getTrainerApp()?.name ?? '-',
|
||||
"bikecontrol_target": core.settings.getLastTarget()?.name ?? '-',
|
||||
if (core.connection.controllerDevices.isNotEmpty)
|
||||
|
||||
@@ -8,6 +8,9 @@ import 'package:bike_control/utils/windows_store_environment.dart';
|
||||
import 'package:bike_control/widgets/ui/toast.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:gotrue/src/types/auth_state.dart';
|
||||
import 'package:prop/prop.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:windows_iap/windows_iap.dart';
|
||||
|
||||
/// Windows-specific IAP service
|
||||
@@ -44,6 +47,32 @@ class WindowsIAPService {
|
||||
_lastCommandDate = await _prefs.read(key: _lastCommandDateKey);
|
||||
_dailyCommandCount = int.tryParse(await _prefs.read(key: _dailyCommandCountKey) ?? '0');
|
||||
_isInitialized = true;
|
||||
|
||||
|
||||
_authSubscription = core.supabase.auth.onAuthStateChange.listen((data) {
|
||||
final AuthChangeEvent event = data.event;
|
||||
final Session? session = data.session;
|
||||
|
||||
Logger.info('event: $event, session: ${session?.user.id} via ${session?.user.email}');
|
||||
|
||||
switch (event) {
|
||||
case AuthChangeEvent.initialSession:
|
||||
case AuthChangeEvent.signedIn:
|
||||
// handle signed in
|
||||
case AuthChangeEvent.signedOut:
|
||||
// handle signed out
|
||||
case AuthChangeEvent.passwordRecovery:
|
||||
// handle password recovery
|
||||
case AuthChangeEvent.tokenRefreshed:
|
||||
// handle token refreshed
|
||||
case AuthChangeEvent.userUpdated:
|
||||
// handle user updated
|
||||
case AuthChangeEvent.userDeleted:
|
||||
// handle user deleted
|
||||
case AuthChangeEvent.mfaChallengeVerified:
|
||||
// handle mfa challenge verified
|
||||
}
|
||||
});
|
||||
} catch (e, s) {
|
||||
recordError(e, s, context: 'Initializing');
|
||||
debugPrint('Failed to initialize Windows IAP: $e');
|
||||
@@ -108,6 +137,8 @@ class WindowsIAPService {
|
||||
/// Get the number of days remaining in the trial
|
||||
int trialDaysRemaining = 0;
|
||||
|
||||
late final StreamSubscription<AuthState> _authSubscription;
|
||||
|
||||
/// Check if the trial has expired
|
||||
bool get isTrialExpired {
|
||||
return !IAPManager.instance.isPurchased.value && hasTrialStarted && trialDaysRemaining <= 0;
|
||||
|
||||
70
lib/utils/requirements/windows.dart
Normal file
70
lib/utils/requirements/windows.dart
Normal file
@@ -0,0 +1,70 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:win32/win32.dart';
|
||||
|
||||
const _hive = HKEY_CURRENT_USER;
|
||||
|
||||
class WindowsProtocolHandler {
|
||||
List<String> getArguments(List<String>? arguments) {
|
||||
if (arguments == null) return ['%s'];
|
||||
|
||||
if (arguments.isEmpty && !arguments.any((e) => e.contains('%s'))) {
|
||||
throw ArgumentError('arguments must contain at least 1 instance of "%s"');
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
void register(String scheme, {String? executable, List<String>? arguments}) {
|
||||
if (defaultTargetPlatform != TargetPlatform.windows) return;
|
||||
|
||||
final prefix = _regPrefix(scheme);
|
||||
final capitalized = scheme[0].toUpperCase() + scheme.substring(1);
|
||||
final args = getArguments(arguments).map((a) => _sanitize(a));
|
||||
final cmd = '${executable ?? Platform.resolvedExecutable} ${args.join(' ')}';
|
||||
|
||||
_regCreateStringKey(_hive, prefix, '', 'URL:$capitalized');
|
||||
_regCreateStringKey(_hive, prefix, 'URL Protocol', '');
|
||||
_regCreateStringKey(_hive, '$prefix\\shell\\open\\command', '', cmd);
|
||||
}
|
||||
|
||||
void unregister(String scheme) {
|
||||
if (defaultTargetPlatform != TargetPlatform.windows) return;
|
||||
|
||||
final txtKey = TEXT(_regPrefix(scheme));
|
||||
try {
|
||||
RegDeleteTree(HKEY_CURRENT_USER, txtKey);
|
||||
} finally {
|
||||
free(txtKey);
|
||||
}
|
||||
}
|
||||
|
||||
String _regPrefix(String scheme) => 'SOFTWARE\\Classes\\$scheme';
|
||||
|
||||
int _regCreateStringKey(int hKey, String key, String valueName, String data) {
|
||||
final txtKey = TEXT(key);
|
||||
final txtValue = TEXT(valueName);
|
||||
final txtData = TEXT(data);
|
||||
try {
|
||||
return RegSetKeyValue(
|
||||
hKey,
|
||||
txtKey,
|
||||
txtValue,
|
||||
REG_SZ,
|
||||
txtData,
|
||||
txtData.length * 2 + 2,
|
||||
);
|
||||
} finally {
|
||||
free(txtKey);
|
||||
free(txtValue);
|
||||
free(txtData);
|
||||
}
|
||||
}
|
||||
|
||||
String _sanitize(String value) {
|
||||
value = value.replaceAll(r'%s', '%1').replaceAll(r'"', '\\"');
|
||||
return '"$value"';
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import 'package:path_provider_windows/path_provider_windows.dart';
|
||||
import 'package:prop/emulators/prefs.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:shared_preferences_windows/shared_preferences_windows.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../../main.dart';
|
||||
@@ -49,6 +50,15 @@ class Settings {
|
||||
final app = getKeyMap();
|
||||
core.actionHandler.init(app);
|
||||
|
||||
try {
|
||||
await Supabase.initialize(
|
||||
url: 'https://pikrcyynovdvogrldfnw.supabase.co',
|
||||
anonKey: const String.fromEnvironment('SUPABASE_ANON_KEY'),
|
||||
);
|
||||
} catch (e, s) {
|
||||
recordError(e, s, context: 'Supabase initialization');
|
||||
}
|
||||
|
||||
// Initialize IAP manager
|
||||
await IAPManager.instance.initialize();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:bike_control/bluetooth/devices/zwift/zwift_clickv2.dart';
|
||||
import 'package:bike_control/pages/login.dart';
|
||||
import 'package:bike_control/pages/markdown.dart';
|
||||
import 'package:bike_control/pages/navigation.dart';
|
||||
import 'package:bike_control/utils/core.dart';
|
||||
@@ -149,6 +150,16 @@ class BKMenuButton extends StatelessWidget {
|
||||
core.connection.disconnectAll();
|
||||
},
|
||||
),
|
||||
MenuButton(
|
||||
child: Text('Login'),
|
||||
onPressed: (c) async {
|
||||
openDrawer(
|
||||
context: context,
|
||||
builder: (c) => LoginPage(),
|
||||
position: OverlayPosition.bottom,
|
||||
);
|
||||
},
|
||||
),
|
||||
MenuDivider(),
|
||||
],
|
||||
if (currentPage == BCPage.logs) ...[
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import app_links
|
||||
import audio_session
|
||||
import bluetooth_low_energy_darwin
|
||||
import device_info_plus
|
||||
@@ -13,6 +14,7 @@ import flutter_local_notifications
|
||||
import flutter_secure_storage_darwin
|
||||
import flutter_volume_controller
|
||||
import gamepads_darwin
|
||||
import google_sign_in_ios
|
||||
import in_app_purchase_storekit
|
||||
import in_app_review
|
||||
import ios_receipt
|
||||
@@ -24,12 +26,14 @@ import package_info_plus
|
||||
import purchases_flutter
|
||||
import screen_retriever_macos
|
||||
import shared_preferences_foundation
|
||||
import sign_in_with_apple
|
||||
import universal_ble
|
||||
import url_launcher_macos
|
||||
import wakelock_plus
|
||||
import window_manager
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||
BluetoothLowEnergyDarwinPlugin.register(with: registry.registrar(forPlugin: "BluetoothLowEnergyDarwinPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
@@ -38,6 +42,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin"))
|
||||
FlutterVolumeControllerPlugin.register(with: registry.registrar(forPlugin: "FlutterVolumeControllerPlugin"))
|
||||
GamepadsDarwinPlugin.register(with: registry.registrar(forPlugin: "GamepadsDarwinPlugin"))
|
||||
FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin"))
|
||||
InAppPurchasePlugin.register(with: registry.registrar(forPlugin: "InAppPurchasePlugin"))
|
||||
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
||||
IosReceiptPlugin.register(with: registry.registrar(forPlugin: "IosReceiptPlugin"))
|
||||
@@ -49,6 +54,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
PurchasesFlutterPlugin.register(with: registry.registrar(forPlugin: "PurchasesFlutterPlugin"))
|
||||
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SignInWithApplePlugin.register(with: registry.registrar(forPlugin: "SignInWithApplePlugin"))
|
||||
UniversalBlePlugin.register(with: registry.registrar(forPlugin: "UniversalBlePlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
PODS:
|
||||
- app_links (6.4.1):
|
||||
- FlutterMacOS
|
||||
- AppAuth (2.0.0):
|
||||
- AppAuth/Core (= 2.0.0)
|
||||
- AppAuth/ExternalUserAgent (= 2.0.0)
|
||||
- AppAuth/Core (2.0.0)
|
||||
- AppAuth/ExternalUserAgent (2.0.0):
|
||||
- AppAuth/Core
|
||||
- AppCheckCore (11.2.0):
|
||||
- GoogleUtilities/Environment (~> 8.0)
|
||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- audio_session (0.0.1):
|
||||
- FlutterMacOS
|
||||
- bluetooth_low_energy_darwin (0.0.1):
|
||||
@@ -18,6 +30,33 @@ PODS:
|
||||
- FlutterMacOS (1.0.0)
|
||||
- gamepads_darwin (0.1.1):
|
||||
- FlutterMacOS
|
||||
- google_sign_in_ios (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- GoogleSignIn (~> 9.0)
|
||||
- GTMSessionFetcher (>= 3.4.0)
|
||||
- GoogleSignIn (9.1.0):
|
||||
- AppAuth (~> 2.0)
|
||||
- AppCheckCore (~> 11.0)
|
||||
- GTMAppAuth (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 3.3)
|
||||
- GoogleUtilities/Environment (8.1.0):
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Logger (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Privacy (8.1.0)
|
||||
- GoogleUtilities/UserDefaults (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GTMAppAuth (5.0.0):
|
||||
- AppAuth/Core (~> 2.0)
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 3.3)
|
||||
- GTMSessionFetcher (3.5.0):
|
||||
- GTMSessionFetcher/Full (= 3.5.0)
|
||||
- GTMSessionFetcher/Core (3.5.0)
|
||||
- GTMSessionFetcher/Full (3.5.0):
|
||||
- GTMSessionFetcher/Core
|
||||
- in_app_purchase_storekit (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -36,6 +75,7 @@ PODS:
|
||||
- FlutterMacOS
|
||||
- package_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- PromisesObjC (2.4.0)
|
||||
- purchases_flutter (9.10.6):
|
||||
- FlutterMacOS
|
||||
- PurchasesHybridCommon (= 17.27.1)
|
||||
@@ -47,6 +87,8 @@ PODS:
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- sign_in_with_apple (0.0.1):
|
||||
- FlutterMacOS
|
||||
- universal_ble (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -58,6 +100,7 @@ PODS:
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
|
||||
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
|
||||
- bluetooth_low_energy_darwin (from `Flutter/ephemeral/.symlinks/plugins/bluetooth_low_energy_darwin/darwin`)
|
||||
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||
@@ -67,6 +110,7 @@ DEPENDENCIES:
|
||||
- flutter_volume_controller (from `Flutter/ephemeral/.symlinks/plugins/flutter_volume_controller/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- gamepads_darwin (from `Flutter/ephemeral/.symlinks/plugins/gamepads_darwin/macos`)
|
||||
- google_sign_in_ios (from `Flutter/ephemeral/.symlinks/plugins/google_sign_in_ios/darwin`)
|
||||
- in_app_purchase_storekit (from `Flutter/ephemeral/.symlinks/plugins/in_app_purchase_storekit/darwin`)
|
||||
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
||||
- ios_receipt (from `Flutter/ephemeral/.symlinks/plugins/ios_receipt/macos`)
|
||||
@@ -78,6 +122,7 @@ DEPENDENCIES:
|
||||
- purchases_flutter (from `Flutter/ephemeral/.symlinks/plugins/purchases_flutter/macos`)
|
||||
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
||||
- shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- sign_in_with_apple (from `Flutter/ephemeral/.symlinks/plugins/sign_in_with_apple/macos`)
|
||||
- universal_ble (from `Flutter/ephemeral/.symlinks/plugins/universal_ble/darwin`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||
@@ -85,10 +130,19 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- AppAuth
|
||||
- AppCheckCore
|
||||
- GoogleSignIn
|
||||
- GoogleUtilities
|
||||
- GTMAppAuth
|
||||
- GTMSessionFetcher
|
||||
- PromisesObjC
|
||||
- PurchasesHybridCommon
|
||||
- RevenueCat
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
|
||||
audio_session:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos
|
||||
bluetooth_low_energy_darwin:
|
||||
@@ -107,6 +161,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral
|
||||
gamepads_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/gamepads_darwin/macos
|
||||
google_sign_in_ios:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/google_sign_in_ios/darwin
|
||||
in_app_purchase_storekit:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/in_app_purchase_storekit/darwin
|
||||
in_app_review:
|
||||
@@ -129,6 +185,8 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos
|
||||
shared_preferences_foundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
|
||||
sign_in_with_apple:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sign_in_with_apple/macos
|
||||
universal_ble:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/universal_ble/darwin
|
||||
url_launcher_macos:
|
||||
@@ -139,6 +197,9 @@ EXTERNAL SOURCES:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: c3185399a5cabc2e610ee5ad52fb7269b84ff869
|
||||
AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063
|
||||
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
|
||||
audio_session: 728ae3823d914f809c485d390274861a24b0904e
|
||||
bluetooth_low_energy_darwin: 50bc79258e60586e4c4bed5948bd31d925f37fac
|
||||
device_info_plus: 1b14eed9bf95428983aed283a8d51cce3d8c4215
|
||||
@@ -148,6 +209,11 @@ SPEC CHECKSUMS:
|
||||
flutter_volume_controller: 25d09126b0d695560f11c80b1311d5063fed882f
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
gamepads_darwin: 07af6c60c282902b66574c800e20b2b26e68fda8
|
||||
google_sign_in_ios: 7336a3372ea93ea56a21e126a0055ffca3723601
|
||||
GoogleSignIn: fcee2257188d5eda57a5e2b6a715550ffff9206d
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
GTMAppAuth: 217a876b249c3c585a54fd6f73e6b58c4f5c4238
|
||||
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
||||
in_app_purchase_storekit: 2342c0a5da86593124d08dd13d920f39a52b273a
|
||||
in_app_review: 866c9b17c87a7b46a395bda43f5d3ca02deb585a
|
||||
ios_receipt: 8741a75f39e6ca0866313b73c69a5b674cf5c98c
|
||||
@@ -156,11 +222,13 @@ SPEC CHECKSUMS:
|
||||
media_key_detector_macos: a93757a483b4b47283ade432b1af9e427c47329f
|
||||
nsd_macos: 1a38a38a33adbb396b4c6f303bc076073514cadc
|
||||
package_info_plus: 12f1c5c2cfe8727ca46cbd0b26677728972d9a5b
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
purchases_flutter: 55ed35144683d8673f0a4b5077e8f4d8291f291e
|
||||
PurchasesHybridCommon: 027f03312519c51056457eb2e4f7ee1c91b61b8f
|
||||
RevenueCat: ecbba580fa453b0d4a0475449b904196d74ef678
|
||||
screen_retriever_macos: 776e0fa5d42c6163d2bf772d22478df4b302b161
|
||||
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||
sign_in_with_apple: a9e97e744e8edc36aefc2723111f652102a7a727
|
||||
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
||||
url_launcher_macos: 175a54c831f4375a6cf895875f716ee5af3888ce
|
||||
wakelock_plus: 9d63063ffb7af1c215209769067c57103bde719d
|
||||
|
||||
@@ -240,6 +240,7 @@
|
||||
33CC110E2044A8840003C045 /* Bundle Framework */,
|
||||
3399D490228B24CF009A79C7 /* ShellScript */,
|
||||
416B733CA2212067A6157BC2 /* [CP] Embed Pods Frameworks */,
|
||||
64E1C1C2337BD399A29F09AF /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -398,6 +399,23 @@
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
64E1C1C2337BD399A29F09AF /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DDE99C1FE0195AFA9D281938 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
import Cocoa
|
||||
import FlutterMacOS
|
||||
import app_links
|
||||
|
||||
@main
|
||||
class AppDelegate: FlutterAppDelegate {
|
||||
|
||||
public override func application(_ application: NSApplication,
|
||||
continue userActivity: NSUserActivity,
|
||||
restorationHandler: @escaping ([any NSUserActivityRestoring]) -> Void) -> Bool {
|
||||
|
||||
guard let url = AppLinks.shared.getUniversalLink(userActivity) else {
|
||||
return false
|
||||
}
|
||||
|
||||
AppLinks.shared.handleLink(link: url.absoluteString)
|
||||
|
||||
return false // Returning true will stop the propagation to other packages
|
||||
}
|
||||
|
||||
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -2,19 +2,25 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.bluetooth</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.google.GIDSignIn</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -48,5 +48,19 @@
|
||||
<string>NSApplication</string>
|
||||
<key>NSAccessibilityUsageDescription</key>
|
||||
<string>BikeControl needs to send keys to your trainer app.</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.googleusercontent.apps.709945926587-0iierajthibf4vhqf85fc7bbpgbdgua2</string>
|
||||
<string>bikecontrol</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>GIDClientID</key>
|
||||
<string>709945926587-0iierajthibf4vhqf85fc7bbpgbdgua2.apps.googleusercontent.com</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -2,19 +2,25 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.bluetooth</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.google.GIDSignIn</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
2
prop
2
prop
Submodule prop updated: a154bf1b7c...9f4cefba4a
248
pubspec.lock
248
pubspec.lock
@@ -16,6 +16,14 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
adaptive_number:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: adaptive_number
|
||||
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -48,6 +56,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.2"
|
||||
app_links:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links
|
||||
sha256: "5f88447519add627fe1cbcab4fd1da3d4fed15b9baf29f28b22535c95ecee3e8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
app_links_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_linux
|
||||
sha256: f5f7173a78609f3dfd4c2ff2c95bd559ab43c80a87dc6a095921d96c05688c81
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
app_links_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_platform_interface
|
||||
sha256: "05f5379577c513b534a29ddea68176a4d4802c46180ee8e2e966257158772a3f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
app_links_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: app_links_web
|
||||
sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -240,6 +280,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
dart_jsonwebtoken:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_jsonwebtoken
|
||||
sha256: "0de65691c1d736e9459f22f654ddd6fd8368a271d4e41aa07e53e6301eff5075"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.1"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -297,6 +345,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.3"
|
||||
ed25519_edwards:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ed25519_edwards
|
||||
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
email_validator:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -538,11 +594,27 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
font_awesome_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: font_awesome_flutter
|
||||
sha256: b9011df3a1fa02993630b8fb83526368cf2206a711259830325bab2f1d2a4eb0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.12.0"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
functions_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: functions_client
|
||||
sha256: "94074d62167ae634127ef6095f536835063a7dc80f2b1aa306d2346ff9023996"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
gamepads:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -640,6 +712,62 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.2.0"
|
||||
google_identity_services_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_identity_services_web
|
||||
sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+1"
|
||||
google_sign_in:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: google_sign_in
|
||||
sha256: "521031b65853b4409b8213c0387d57edaad7e2a949ce6dea0d8b2afc9cb29763"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.0"
|
||||
google_sign_in_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_android
|
||||
sha256: "5ec98ab35387c68c0050495bb211bd88375873723a80fae7c2e9266ea0bdd8bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.7"
|
||||
google_sign_in_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_ios
|
||||
sha256: ac1e4c1205267cb7999d1d81333fccffdfda29e853f434bbaf71525498bb6950
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
google_sign_in_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_platform_interface
|
||||
sha256: "7f59208c42b415a3cca203571128d6f84f885fead2d5b53eb65a9e27f2965bb5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
google_sign_in_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: google_sign_in_web
|
||||
sha256: "2fc1f941e6443b2d6984f4056a727a3eaeab15d8ee99ba7125d79029be75a1da"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
gotrue:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: gotrue
|
||||
sha256: f7b52008311941a7c3e99f9590c4ee32dfc102a5442e43abf1b287d9f8cc39b2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.18.0"
|
||||
gsettings:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -900,6 +1028,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.16"
|
||||
jwt_decode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jwt_decode
|
||||
sha256: d2e9f68c052b2225130977429d30f187aa1981d789c76ad104a32243cfdebfbb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
keypress_simulator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1306,6 +1442,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
posix:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1314,6 +1458,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.3"
|
||||
postgrest:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: postgrest
|
||||
sha256: f4b6bb24b465c47649243ef0140475de8a0ec311dc9c75ebe573b2dcabb10460
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1385,6 +1537,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
realtime_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: realtime_client
|
||||
sha256: "5268afc208d02fb9109854d262c1ebf6ece224cd285199ae1d2f92d2ff49dbf1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
restart_app:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1394,6 +1554,14 @@ packages:
|
||||
url: "https://github.com/maple135790/restart_app.git"
|
||||
source: git
|
||||
version: "1.4.0"
|
||||
retry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: retry
|
||||
sha256: "822e118d5b3aafed083109c72d5f484c6dc66707885e07c0fbcb8b986bba7efc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
rxdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1531,6 +1699,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
sign_in_button:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sign_in_button
|
||||
sha256: "7bcd5e3ca5f80578da6a92b8749badf4003cf4dc578b5cb737b9082871354ff8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
sign_in_with_apple:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sign_in_with_apple
|
||||
sha256: "8bd875c8e8748272749eb6d25b896f768e7e9d60988446d543fe85a37a2392b8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
sign_in_with_apple_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sign_in_with_apple_platform_interface
|
||||
sha256: "981bca52cf3bb9c3ad7ef44aace2d543e5c468bb713fd8dda4275ff76dfa6659"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
sign_in_with_apple_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sign_in_with_apple_web
|
||||
sha256: f316400827f52cafcf50d00e1a2e8a0abc534ca1264e856a81c5f06bd5b10fed
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
skeletonizer:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1568,6 +1768,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
storage_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: storage_client
|
||||
sha256: "1c61b19ed9e78f37fdd1ca8b729ab8484e6c8fe82e15c87e070b861951183657"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1584,6 +1792,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
supabase:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: supabase
|
||||
sha256: cc039f63a3168386b3a4f338f3bff342c860d415a3578f3fbe854024aee6f911
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.10.2"
|
||||
supabase_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: supabase_flutter
|
||||
sha256: "92b2416ecb6a5c3ed34cf6e382b35ce6cc8921b64f2a9299d5d28968d42b09bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.12.0"
|
||||
sync_http:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1785,6 +2009,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
webdriver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1896,6 +2136,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.0.4"
|
||||
yet_another_json_isolate:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yet_another_json_isolate
|
||||
sha256: fe45897501fa156ccefbfb9359c9462ce5dec092f05e8a56109db30be864f01e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
sdks:
|
||||
dart: ">=3.10.3 <4.0.0"
|
||||
flutter: ">=3.38.4"
|
||||
|
||||
@@ -30,6 +30,12 @@ dependencies:
|
||||
flutter_md: ^0.0.7
|
||||
permission_handler: ^12.0.1
|
||||
dartx: any
|
||||
|
||||
supabase_flutter: ^2.12.0
|
||||
sign_in_button: ^4.0.1
|
||||
google_sign_in: ^7.2.0
|
||||
sign_in_with_apple: ^7.0.1
|
||||
|
||||
nsd: ^4.0.3
|
||||
image_picker: ^1.1.2
|
||||
in_app_review: ^2.0.11
|
||||
@@ -121,4 +127,5 @@ msix_config:
|
||||
store: true
|
||||
logo_path: web/icons/Icon-512.png
|
||||
build_windows: false
|
||||
protocol_activation: https, bikecontrol
|
||||
capabilities: internetClient,bluetooth,inputInjectionBrokered
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <app_links/app_links_plugin_c_api.h>
|
||||
#include <bluetooth_low_energy_windows/bluetooth_low_energy_windows_plugin_c_api.h>
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
@@ -22,6 +23,8 @@
|
||||
#include <windows_iap/windows_iap_plugin_c_api.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
AppLinksPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
|
||||
BluetoothLowEnergyWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("BluetoothLowEnergyWindowsPluginCApi"));
|
||||
FileSelectorWindowsRegisterWithRegistrar(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
app_links
|
||||
bluetooth_low_energy_windows
|
||||
file_selector_windows
|
||||
flutter_secure_storage_windows
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <flutter/method_channel.h>
|
||||
#include <flutter/standard_method_codec.h>
|
||||
#include "app_links/app_links_plugin_c_api.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -44,9 +45,54 @@ namespace
|
||||
|
||||
} // namespace
|
||||
|
||||
bool SendAppLinkToInstance(const std::wstring &title)
|
||||
{
|
||||
// Find our exact window
|
||||
HWND hwnd = ::FindWindow(L"FLUTTER_RUNNER_WIN32_WINDOW", title.c_str());
|
||||
|
||||
if (hwnd)
|
||||
{
|
||||
// Dispatch new link to current window
|
||||
SendAppLink(hwnd);
|
||||
|
||||
// (Optional) Restore our window to front in same state
|
||||
WINDOWPLACEMENT place = {sizeof(WINDOWPLACEMENT)};
|
||||
GetWindowPlacement(hwnd, &place);
|
||||
|
||||
switch (place.showCmd)
|
||||
{
|
||||
case SW_SHOWMAXIMIZED:
|
||||
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
|
||||
break;
|
||||
case SW_SHOWMINIMIZED:
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
break;
|
||||
default:
|
||||
ShowWindow(hwnd, SW_NORMAL);
|
||||
break;
|
||||
}
|
||||
|
||||
SetWindowPos(0, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);
|
||||
SetForegroundWindow(hwnd);
|
||||
// END (Optional) Restore
|
||||
|
||||
// Window has been found, don't create another one.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||
_In_ wchar_t *command_line, _In_ int show_command)
|
||||
{
|
||||
// Replace "example" with the generated title found as parameter of `window.Create` in this file.
|
||||
// You may ignore the result if you need to create another window.
|
||||
if (SendAppLinkToInstance(L"BikeControl"))
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Attach to console when present (e.g., 'flutter run') or create a
|
||||
// new console when running with a debugger.
|
||||
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent())
|
||||
|
||||
Reference in New Issue
Block a user