1
0
mirror of https://github.com/krawieck/lemmur/ synced 2024-12-17 19:09:07 +01:00
lemmur-app-android/lib/stores/accounts_store.dart

166 lines
4.7 KiB
Dart

import 'dart:convert';
import 'package:lemmy_api_client/lemmy_api_client.dart';
import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
part 'accounts_store.g.dart';
class AccountsStore extends _AccountsStore with _$AccountsStore {}
abstract class _AccountsStore with Store {
ReactionDisposer _saveReactionDisposer;
_AccountsStore() {
// persistently save settings each time they are changed
_saveReactionDisposer = reaction(
// TODO: does not react to deep changes in users and tokens
(_) => [
users.asObservable(),
tokens.asObservable(),
_defaultAccount,
_defaultAccounts.asObservable(),
],
(_) {
save();
},
);
}
void dispose() {
_saveReactionDisposer();
}
void load() async {
var prefs = await SharedPreferences.getInstance();
// set saved settings or create defaults
// TODO: load saved users and tokens
users = ObservableMap();
tokens = ObservableMap();
_defaultAccount = prefs.getString('defaultAccount');
_defaultAccounts = ObservableMap.of(Map.castFrom(
jsonDecode(prefs.getString('defaultAccounts') ?? 'null') ?? {}));
}
void save() async {
var prefs = await SharedPreferences.getInstance();
await prefs.setString('defaultAccount', _defaultAccount);
await prefs.setString('defaultAccounts', jsonEncode(_defaultAccounts));
await prefs.setString('users', jsonEncode(users));
await prefs.setString('tokens', jsonEncode(tokens));
}
/// if path to tokens map exists, it exists for users as well
/// `users['instanceUrl']['username']`
@observable
ObservableMap<String, ObservableMap<String, User>> users;
/// if path to users map exists, it exists for tokens as well
/// `tokens['instanceUrl']['username']`
@observable
ObservableMap<String, ObservableMap<String, Jwt>> tokens;
/// default account for a given instance
/// map where keys are instanceUrls and values are usernames
@observable
ObservableMap<String, String> _defaultAccounts;
/// default account for the app
/// username@instanceUrl
@observable
String _defaultAccount;
@computed
User get defaultUser {
var userTag = _defaultAccount.split('@');
return users[userTag[1]][userTag[0]];
}
@computed
Jwt get defaultToken {
var userTag = _defaultAccount.split('@');
return tokens[userTag[1]][userTag[0]];
}
User defaultUserFor(String instanceUrl) =>
Computed(() => users[instanceUrl][_defaultAccounts[instanceUrl]]).value;
Jwt defaultTokenFor(String instanceUrl) =>
Computed(() => tokens[instanceUrl][_defaultAccounts[instanceUrl]]).value;
@action
void setDefaultAccount(String instanceUrl, String username) {
_defaultAccount = '$username@$instanceUrl';
}
@action
void setDefaultAccountFor(String instanceUrl, String username) {
_defaultAccounts[instanceUrl] = username;
}
bool isAnonymousFor(String instanceUrl) =>
Computed(() => users[instanceUrl].isEmpty).value;
@computed
bool get hasNoAccount => users.values.every((e) => e.isEmpty);
/// adds a new account
/// if it's the first account ever the account is
/// set as default for the app
/// if it's the first account for an instance the account is
/// set as default for that instance
@action
Future<void> addAccount(
String instanceUrl,
String usernameOrEmail,
String password,
) async {
if (!users.containsKey(instanceUrl)) {
throw Exception('No such instance was added');
}
var lemmy = LemmyApi(instanceUrl).v1;
var token = await lemmy.login(
usernameOrEmail: usernameOrEmail,
password: password,
);
var userData =
await lemmy.getSite(auth: token.raw).then((value) => value.myUser);
// first account for this instance
if (users[instanceUrl].isEmpty) {
// first account ever
if (hasNoAccount) {
setDefaultAccount(instanceUrl, userData.name);
}
setDefaultAccountFor(instanceUrl, userData.name);
}
users[instanceUrl][userData.name] = userData;
tokens[instanceUrl][userData.name] = token;
}
/// adds a new instance with no accounts associated with it.
/// Additionally makes a test GET /site request to check if the instance exists
@action
Future<void> addInstance(String instanceUrl) async {
if (users.containsKey(instanceUrl)) {
throw Exception('This instance has already been added');
}
try {
await LemmyApi(instanceUrl).v1.getSite();
// ignore: avoid_catches_without_on_clauses
} catch (_) {
throw Exception('This instance seems to not exist');
}
users[instanceUrl] = ObservableMap();
tokens[instanceUrl] = ObservableMap();
}
// TODO: add a way of removing accounts/instances
}