sign in with pocketbase working
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/// PocketBase sign-in state. Local tx/bank data is unchanged by auth.
|
||||
library;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:pocketbase/pocketbase.dart';
|
||||
|
||||
import '../services/storage_service.dart';
|
||||
import '../utils/constants.dart';
|
||||
|
||||
/// Owns the PocketBase client, session persistence, and login/logout.
|
||||
class AuthController extends ChangeNotifier {
|
||||
AuthController(this._storage);
|
||||
|
||||
final StorageService _storage;
|
||||
PocketBase? _client;
|
||||
|
||||
PocketBase get client {
|
||||
final pb = _client;
|
||||
if (pb == null) {
|
||||
throw StateError('AuthController.init() must be called before use.');
|
||||
}
|
||||
return pb;
|
||||
}
|
||||
|
||||
bool get isLoggedIn => _client?.authStore.isValid ?? false;
|
||||
|
||||
RecordModel? get user => _client?.authStore.record;
|
||||
|
||||
String? get email {
|
||||
final value = user?.getStringValue('email');
|
||||
return value == null || value.isEmpty ? null : value;
|
||||
}
|
||||
|
||||
String? get name {
|
||||
final value = user?.getStringValue('name');
|
||||
return value == null || value.isEmpty ? null : value;
|
||||
}
|
||||
|
||||
String get displayName {
|
||||
final n = name;
|
||||
if (n != null && n.isNotEmpty) return n;
|
||||
final e = email;
|
||||
if (e != null && e.isNotEmpty) return e.split('@').first;
|
||||
return 'Account';
|
||||
}
|
||||
|
||||
String get initials {
|
||||
final source = name ?? email ?? '?';
|
||||
final parts = source.trim().split(RegExp(r'\s+'));
|
||||
if (parts.length >= 2 && parts[0].isNotEmpty && parts[1].isNotEmpty) {
|
||||
return '${parts[0][0]}${parts[1][0]}'.toUpperCase();
|
||||
}
|
||||
if (source.isNotEmpty) return source[0].toUpperCase();
|
||||
return '?';
|
||||
}
|
||||
|
||||
Future<void> init() async {
|
||||
final store = AsyncAuthStore(
|
||||
save: (String data) async {
|
||||
if (data.isEmpty) {
|
||||
await _storage.clearPocketBaseAuth();
|
||||
} else {
|
||||
await _storage.setPocketBaseAuth(data);
|
||||
}
|
||||
},
|
||||
initial: _storage.pocketBaseAuth,
|
||||
);
|
||||
_client = PocketBase(kPocketBaseUrl, authStore: store);
|
||||
_client!.authStore.onChange.listen((_) => notifyListeners());
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> login({
|
||||
required String email,
|
||||
required String password,
|
||||
}) async {
|
||||
await client
|
||||
.collection(kPocketBaseUsersCollection)
|
||||
.authWithPassword(email.trim(), password);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
client.authStore.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@@ -278,11 +278,14 @@ class TxMetaController extends ChangeNotifier {
|
||||
: (inheritedNotes ?? ''));
|
||||
|
||||
final recurring = stored?.recurring ?? template?.recurring ?? false;
|
||||
final internalTransfer =
|
||||
stored?.internalTransfer ?? template?.internalTransfer ?? false;
|
||||
|
||||
return TxMeta(
|
||||
labelIds: List<String>.of(labelIds),
|
||||
notes: notes,
|
||||
recurring: recurring,
|
||||
internalTransfer: internalTransfer,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -570,6 +573,29 @@ class TxMetaController extends ChangeNotifier {
|
||||
tx.exactKey: TxExactTemplate(
|
||||
notes: existing.notes.isNotEmpty ? existing.notes : current.notes,
|
||||
recurring: recurring,
|
||||
internalTransfer:
|
||||
existing.internalTransfer || current.internalTransfer,
|
||||
),
|
||||
};
|
||||
_schedulePersist();
|
||||
}
|
||||
|
||||
Future<void> setInternalTransfer(
|
||||
BankTransaction tx,
|
||||
bool internalTransfer,
|
||||
) async {
|
||||
final current = metaFor(tx);
|
||||
_byId = {
|
||||
..._byId,
|
||||
tx.id: current.copyWith(internalTransfer: internalTransfer),
|
||||
};
|
||||
final existing = _exactTemplates[tx.exactKey] ?? const TxExactTemplate();
|
||||
_exactTemplates = {
|
||||
..._exactTemplates,
|
||||
tx.exactKey: TxExactTemplate(
|
||||
notes: existing.notes.isNotEmpty ? existing.notes : current.notes,
|
||||
recurring: existing.recurring || current.recurring,
|
||||
internalTransfer: internalTransfer,
|
||||
),
|
||||
};
|
||||
_schedulePersist();
|
||||
@@ -604,7 +630,12 @@ class TxMetaController extends ChangeNotifier {
|
||||
if (!applying) {
|
||||
final current = metaFor(tx);
|
||||
final existing = _exactTemplates[tx.exactKey] ?? const TxExactTemplate();
|
||||
if (trimmed.isEmpty && !existing.recurring && !current.recurring) {
|
||||
final keepTemplate = trimmed.isNotEmpty ||
|
||||
existing.recurring ||
|
||||
current.recurring ||
|
||||
existing.internalTransfer ||
|
||||
current.internalTransfer;
|
||||
if (!keepTemplate) {
|
||||
_exactTemplates = Map.of(_exactTemplates)..remove(tx.exactKey);
|
||||
} else {
|
||||
_exactTemplates = {
|
||||
@@ -612,6 +643,8 @@ class TxMetaController extends ChangeNotifier {
|
||||
tx.exactKey: TxExactTemplate(
|
||||
notes: trimmed,
|
||||
recurring: existing.recurring || current.recurring,
|
||||
internalTransfer:
|
||||
existing.internalTransfer || current.internalTransfer,
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -641,6 +674,10 @@ class TxMetaController extends ChangeNotifier {
|
||||
return setRecurring(tx, !metaFor(tx).recurring);
|
||||
}
|
||||
|
||||
Future<void> toggleInternalTransfer(BankTransaction tx) {
|
||||
return setInternalTransfer(tx, !metaFor(tx).internalTransfer);
|
||||
}
|
||||
|
||||
/// Search description, notes, label name, and date.
|
||||
List<BankTransaction> search(
|
||||
List<BankTransaction> txs,
|
||||
@@ -751,7 +788,9 @@ class TxMetaController extends ChangeNotifier {
|
||||
final totals = <String, double>{};
|
||||
for (final tx in txs) {
|
||||
if (tx.amount >= 0) continue;
|
||||
final ids = metaFor(tx).labelIds;
|
||||
final meta = metaFor(tx);
|
||||
if (meta.internalTransfer) continue;
|
||||
final ids = meta.labelIds;
|
||||
if (ids.isEmpty) continue;
|
||||
final amount = tx.amount.abs();
|
||||
for (final id in ids) {
|
||||
@@ -766,7 +805,8 @@ class TxMetaController extends ChangeNotifier {
|
||||
var total = 0.0;
|
||||
for (final tx in txs) {
|
||||
if (tx.amount >= 0) continue;
|
||||
if (!metaFor(tx).hasLabel) continue;
|
||||
final meta = metaFor(tx);
|
||||
if (meta.internalTransfer || !meta.hasLabel) continue;
|
||||
total += tx.amount.abs();
|
||||
}
|
||||
return total;
|
||||
@@ -787,6 +827,7 @@ class TxMetaController extends ChangeNotifier {
|
||||
}
|
||||
for (final tx in txs) {
|
||||
if (tx.amount >= 0) continue;
|
||||
if (metaFor(tx).internalTransfer) continue;
|
||||
final parsed = DateTime.tryParse(tx.date);
|
||||
if (parsed == null) continue;
|
||||
if (parsed.year != month.year || parsed.month != month.month) continue;
|
||||
|
||||
Reference in New Issue
Block a user