Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions lib/providers/sync_providers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,20 @@ final s3ConfigProvider = FutureProvider<CloudServiceConfig?>((ref) async {
});

final authServiceProvider = FutureProvider<CloudAuthService>((ref) async {
final activeAsync = ref.watch(activeCloudConfigProvider);
if (!activeAsync.hasValue) {
return NoopAuthService();
}

final config = activeAsync.value!;
final config = await ref.watch(activeCloudConfigProvider.future);
if (!config.valid || config.type == CloudBackendType.local) {
return NoopAuthService();
}

try {
// BeeCount Cloud 必须复用同步引擎持有的唯一 provider/auth 实例。
// 多个实例虽然共用 SharedPreferences,却各自缓存 session;这会让 2FA
// 登录成功后同步实例仍停留在未登录状态。
if (config.type == CloudBackendType.beecountCloud) {
final provider = await ref.watch(beecountCloudProviderInstance.future);
return provider?.auth ?? NoopAuthService();
}

final services = await createCloudServices(config);
if (services.auth != null) {
return services.auth!;
Expand Down Expand Up @@ -488,10 +491,7 @@ final syncServiceProvider = Provider<SyncService>((ref) {
/// 用于 SyncEngine 和其他需要直接访问 BeeCount Cloud API 的场景
final beecountCloudProviderInstance =
FutureProvider<BeeCountCloudProvider?>((ref) async {
final configAsync = ref.watch(activeCloudConfigProvider);
if (!configAsync.hasValue) return null;

final config = configAsync.value!;
final config = await ref.watch(activeCloudConfigProvider.future);
if (!config.valid || config.type != CloudBackendType.beecountCloud) {
return null;
}
Expand Down
36 changes: 36 additions & 0 deletions test/providers/beecount_cloud_auth_provider_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flutter_cloud_sync/flutter_cloud_sync.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'package:beecount/providers/sync_providers.dart';

void main() {
TestWidgetsFlutterBinding.ensureInitialized();

setUp(() {
SharedPreferences.setMockInitialValues({});
});

test('BeeCount Cloud UI auth and SyncEngine share one auth instance',
() async {
const config = CloudServiceConfig(
type: CloudBackendType.beecountCloud,
name: 'BeeCount Cloud',
beecountCloudBaseUrl: 'https://cloud.example.com',
beecountCloudApiPrefix: '/api/v1',
);
final container = ProviderContainer(
overrides: [
activeCloudConfigProvider.overrideWith((ref) async => config),
],
);
addTearDown(container.dispose);

final provider = await container.read(beecountCloudProviderInstance.future);
final auth = await container.read(authServiceProvider.future);

expect(provider, isNotNull);
expect(identical(auth, provider!.auth), isTrue);
});
}