Require desktopClientId rather than defaulting it to empty
Some checks are pending
file length / file-length (push) Waiting to run
palette drift / palette (push) Waiting to run

An optional '' default reads as "this parameter is usually irrelevant", and
it made `avoid_redundant_argument_values` fire in the first app to pass ''
explicitly -- pushing that app toward deleting the argument, which is exactly
the line that must stay for when the Desktop client id arrives.

Requiring it forces each app to state which halves it configured. Passing ''
still means "not configured"; it just has to be said out loud.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CFSGeWxHPY5rHUGrPqhcmG
This commit is contained in:
Krzysztof Rudnicki 2026-08-22 18:47:10 +02:00
parent 2298fd4ba2
commit 79130a6dd7
4 changed files with 35 additions and 12 deletions

View File

@ -26,7 +26,7 @@ dependencies:
crdt_sync_flutter:
git:
url: https://github.com/kuhyx/utils
ref: crdt_sync_flutter-v0.2.0
ref: crdt_sync_flutter-v0.2.1
path: crdt_sync_flutter
```

View File

@ -22,10 +22,12 @@ import 'package:crdt_sync_flutter/src/google_sign_in.dart';
///
/// [serverClientId] is the **Web** OAuth client id (the audience for the
/// plugin's tokens); [desktopClientId] is a **Desktop**-type client, the only
/// type permitted to redirect to loopback.
/// type permitted to redirect to loopback. Both are required, and passing ''
/// is how an app says it has not configured that half -- explicit, because a
/// silently-defaulted '' is how a button that can never succeed gets shipped.
bool googleAnySignInSupported({
required String serverClientId,
String desktopClientId = '',
required String desktopClientId,
}) =>
googleSignInSupported(serverClientId) ||
desktopSignInSupported(desktopClientId);
@ -59,7 +61,7 @@ enum GoogleFlow {
/// Picks the flow for this platform and configuration.
GoogleFlow googleFlowFor({
required String serverClientId,
String desktopClientId = '',
required String desktopClientId,
}) {
if (googleSignInSupported(serverClientId)) return GoogleFlow.plugin;
if (desktopSignInSupported(desktopClientId)) return GoogleFlow.desktop;
@ -72,7 +74,7 @@ GoogleFlow googleFlowFor({
/// back to the password path either way.
Future<String?> googleAnyIdToken({
required String serverClientId,
String desktopClientId = '',
required String desktopClientId,
}) async {
switch (googleFlowFor(
serverClientId: serverClientId,

View File

@ -4,7 +4,7 @@ description: >-
persisted per-install device id, and a one-call bootstrap. Removes the
~150 lines of firebase_backend.dart every consuming app was copying.
publish_to: 'none'
version: 0.2.0
version: 0.2.1
environment:
sdk: ^3.12.2

View File

@ -29,13 +29,22 @@ void main() {
});
test('is false when neither half is configured', () {
expect(googleAnySignInSupported(serverClientId: ''), isFalse);
expect(
googleAnySignInSupported(serverClientId: '', desktopClientId: ''),
isFalse,
);
});
test('is false on this host when only the plugin half is configured', () {
// The plugin does not run on Linux, so a Web client id alone buys
// nothing here -- and the button must not appear.
expect(googleAnySignInSupported(serverClientId: 'web-cid'), isFalse);
expect(
googleAnySignInSupported(
serverClientId: 'web-cid',
desktopClientId: '',
),
isFalse,
);
});
});
@ -48,25 +57,37 @@ void main() {
});
test('picks nothing when neither half is configured', () {
expect(googleFlowFor(serverClientId: ''), GoogleFlow.none);
expect(
googleFlowFor(serverClientId: '', desktopClientId: ''),
GoogleFlow.none,
);
});
test('picks nothing when only the plugin half is configured here', () {
// The plugin does not run on Linux, so a Web client id alone must not
// route anywhere -- that would be a button that cannot succeed.
expect(googleFlowFor(serverClientId: 'web-cid'), GoogleFlow.none);
expect(
googleFlowFor(serverClientId: 'web-cid', desktopClientId: ''),
GoogleFlow.none,
);
});
});
group('googleAnyIdToken', () {
test('returns null when no flow is available', () async {
expect(await googleAnyIdToken(serverClientId: ''), isNull);
expect(
await googleAnyIdToken(serverClientId: '', desktopClientId: ''),
isNull,
);
});
test('returns null when the plugin half alone is configured', () async {
// Would reach the plugin's platform channel if the gate were wrong,
// which throws rather than returning null.
expect(await googleAnyIdToken(serverClientId: 'web-cid'), isNull);
expect(
await googleAnyIdToken(serverClientId: 'web-cid', desktopClientId: ''),
isNull,
);
});
});
}