blob: fba7a8be8b14102ed7d31727a9946b0440b01e9b [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/// Since this file includes Sky/Mojo, it will need to be mocked out for unit tests.
/// Unfortunately, imports can't be replaced, so the best thing to do is to swap out the whole file.
///
/// The goal of the SettingsManager is to handle viewing and editing of the
/// Croupier Settings.
/// loadSettings: Get the settings of the current player or specified userID.
/// saveSettings: For the current player and their userID, save settings.
/// In the background, these values will be synced.
/// When setting up a sync group, the userIDs are very important.
import '../../logic/croupier_settings.dart' as util;
import 'croupier_client.dart' show CroupierClient;
import 'util.dart' as util;
import 'dart:async';
import 'dart:convert' show UTF8, JSON;
import 'package:ether/syncbase_client.dart'
show SyncbaseNoSqlDatabase, SyncbaseTable, WatchChange, WatchChangeTypes;
typedef void updateCallbackT(String key, String value);
class SettingsManager {
final updateCallbackT updateCallback;
final CroupierClient _cc;
SyncbaseTable tb;
SyncbaseTable tbUser;
SettingsManager([this.updateCallback]) : _cc = new CroupierClient();
Future _prepareSettingsTable() async {
if (tb != null && tbUser != null) {
return; // Then we're already prepared.
}
SyncbaseNoSqlDatabase db = await _cc.createDatabase();
tb = await _cc.createTable(db, util.tableNameSettings);
tbUser = await _cc.createTable(db, util.tableNameSettingsUser);
// Start to watch the stream for the shared settings table.
Stream<WatchChange> watchStream = db.watch(util.tableNameSettings, '', await db.getResumeMarker());
_startWatch(watchStream); // Don't wait for this future.
}
Future<String> load([int userID]) async {
util.log('SettingsManager.load');
await _prepareSettingsTable();
if (userID == null) {
return _tryReadData(tbUser, "settings");
}
return _tryReadData(tb, "${userID}");
}
Future<String> _tryReadData(SyncbaseTable st, String rowkey) async {
var row = st.row(rowkey);
if (!(await row.exists())) {
print("${rowkey} did not exist");
return null;
}
return UTF8.decode(await row.get());
}
// Since only the current user is allowed to save, we should also save to the
// user's personal settings as well.
Future save(int userID, String jsonString) async {
util.log('SettingsManager.save');
await _prepareSettingsTable();
await tbUser.row("settings").put(UTF8.encode(jsonString));
await tb.row("${userID}").put(UTF8.encode(jsonString));
}
Future _startWatch(Stream<WatchChange> watchStream) async {
util.log('Settings watching for changes...');
// This stream never really ends, so I guess we'll watch forever.
await for (WatchChange wc in watchStream) {
assert(wc.tableName == util.tableNameSettings);
util.log('Watch Key: ${wc.rowName}');
util.log('Watch Value ${UTF8.decode(wc.valueBytes)}');
String key = wc.rowName;
String value;
switch (wc.changeType) {
case WatchChangeTypes.put:
value = UTF8.decode(wc.valueBytes);
break;
case WatchChangeTypes.delete:
value = null;
break;
default:
assert(false);
}
if (this.updateCallback != null) {
this.updateCallback(key, value);
}
}
}
}