feat: import Chinese-localized Buzz source snapshot
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import '../auth/auth_provider.dart';
|
||||
import 'community.dart';
|
||||
import 'community_storage.dart';
|
||||
|
||||
final communityStorageProvider = Provider<CommunityStorage>((ref) {
|
||||
return CommunityStorage();
|
||||
});
|
||||
|
||||
class CommunityListNotifier extends AsyncNotifier<List<Community>> {
|
||||
@override
|
||||
Future<List<Community>> build() async {
|
||||
final storage = ref.read(communityStorageProvider);
|
||||
return storage.loadAll();
|
||||
}
|
||||
|
||||
/// Add a community. If one with the same relay URL already exists, update
|
||||
/// its credentials instead. Returns the effective community ID.
|
||||
Future<String> addCommunity(Community community) async {
|
||||
final storage = ref.read(communityStorageProvider);
|
||||
final current = state.value ?? [];
|
||||
|
||||
// If a community with the same relay URL exists, update its credentials
|
||||
// instead of creating a duplicate entry.
|
||||
final existingIndex = current.indexWhere(
|
||||
(w) => w.relayUrl == community.relayUrl,
|
||||
);
|
||||
if (existingIndex >= 0) {
|
||||
final existing = current[existingIndex];
|
||||
final updated = existing.copyWith(
|
||||
pubkey: community.pubkey,
|
||||
nsec: community.nsec,
|
||||
);
|
||||
await storage.save(updated);
|
||||
final updatedList = [...current];
|
||||
updatedList[existingIndex] = updated;
|
||||
state = AsyncData(updatedList);
|
||||
return existing.id;
|
||||
}
|
||||
|
||||
await storage.save(community);
|
||||
state = AsyncData([...current, community]);
|
||||
return community.id;
|
||||
}
|
||||
|
||||
Future<void> removeCommunity(String id) async {
|
||||
final storage = ref.read(communityStorageProvider);
|
||||
await storage.remove(id);
|
||||
|
||||
final current = state.value ?? [];
|
||||
state = AsyncData(current.where((w) => w.id != id).toList());
|
||||
|
||||
// If we removed the active community, switch to another or sign out.
|
||||
final activeId = await storage.loadActiveId();
|
||||
if (activeId == id) {
|
||||
final remaining = state.value ?? [];
|
||||
if (remaining.isNotEmpty) {
|
||||
await switchCommunity(remaining.first.id);
|
||||
} else {
|
||||
await storage.clearActiveId();
|
||||
// Invalidate auth so it re-evaluates against the now-empty storage
|
||||
// and transitions to unauthenticated.
|
||||
ref.invalidate(authProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> switchCommunity(String id) async {
|
||||
final storage = ref.read(communityStorageProvider);
|
||||
await storage.saveActiveId(id);
|
||||
// Reassign list state to trigger activeCommunityProvider (which watches
|
||||
// communityListProvider.future) to rebuild and pick up the new active ID.
|
||||
// We can't use ref.invalidate(activeCommunityProvider) here because that
|
||||
// creates a circular dependency — activeCommunityProvider watches us.
|
||||
state = AsyncData([...state.value ?? []]);
|
||||
// Invalidate auth so AuthState.community reflects the new active community.
|
||||
ref.invalidate(authProvider);
|
||||
}
|
||||
|
||||
Future<void> renameCommunity(String id, String name) async {
|
||||
final storage = ref.read(communityStorageProvider);
|
||||
final current = state.value ?? [];
|
||||
final index = current.indexWhere((w) => w.id == id);
|
||||
if (index < 0) return;
|
||||
|
||||
final updated = current[index].copyWith(name: name);
|
||||
await storage.save(updated);
|
||||
|
||||
final updatedList = [...current];
|
||||
updatedList[index] = updated;
|
||||
state = AsyncData(updatedList);
|
||||
}
|
||||
}
|
||||
|
||||
final communityListProvider =
|
||||
AsyncNotifierProvider<CommunityListNotifier, List<Community>>(
|
||||
CommunityListNotifier.new,
|
||||
);
|
||||
|
||||
/// The currently active community, derived from the stored active ID and
|
||||
/// the community list.
|
||||
final activeCommunityProvider = FutureProvider<Community?>((ref) async {
|
||||
final communities = await ref.watch(communityListProvider.future);
|
||||
final storage = ref.read(communityStorageProvider);
|
||||
final activeId = await storage.loadActiveId();
|
||||
|
||||
if (communities.isEmpty) return null;
|
||||
|
||||
if (activeId == null) {
|
||||
// No active ID stored but communities exist — fall back to first.
|
||||
await storage.saveActiveId(communities.first.id);
|
||||
return communities.first;
|
||||
}
|
||||
|
||||
try {
|
||||
return communities.firstWhere((w) => w.id == activeId);
|
||||
} on StateError {
|
||||
// Active ID points to a community that no longer exists.
|
||||
// Fall back to first community.
|
||||
if (communities.isNotEmpty) {
|
||||
await storage.saveActiveId(communities.first.id);
|
||||
return communities.first;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user