Skip to content

Commit

Permalink
Merge branch 'mobile-sync-defaults-to-false'
Browse files Browse the repository at this point in the history
  • Loading branch information
inetic committed Sep 25, 2024
2 parents cd0f15e + beb0790 commit 19b7895
Show file tree
Hide file tree
Showing 11 changed files with 442 additions and 33 deletions.
23 changes: 15 additions & 8 deletions lib/app/cubits/power_control.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class PowerControlState {
return S.current.messageNetworkIsUnavailable;
}
}

@override
String toString() =>
"PowerControlState($connectivityType, $networkMode, syncOnMobile:$syncOnMobile, ...)";
}

class PowerControl extends Cubit<PowerControlState> with AppLogger {
Expand Down Expand Up @@ -112,10 +116,8 @@ class PowerControl extends Cubit<PowerControlState> with AppLogger {
return;
}

emitUnlessClosed(state.copyWith(syncOnMobile: value));

await _settings.setSyncOnMobileEnabled(value);
await _refresh();
await _refresh(syncOnMobile: value);
}

Future<void> setPortForwardingEnabled(bool value) async {
Expand Down Expand Up @@ -149,8 +151,12 @@ class PowerControl extends Cubit<PowerControlState> with AppLogger {
}
}

Future<void> _onConnectivityChange(ConnectivityResult result) async {
if (result == state.connectivityType) {
Future<void> _onConnectivityChange(ConnectivityResult result,
{bool? syncOnMobile = null}) async {
syncOnMobile ??= state.syncOnMobile;

if (result == state.connectivityType &&
syncOnMobile == state.syncOnMobile) {
// The Cubit/Bloc machinery knows not to rebuild widgets if the state
// doesn't change, but in this function we also call
// `_session.bindNetwork` which we don't necessarily want to do if the
Expand All @@ -164,7 +170,7 @@ class PowerControl extends Cubit<PowerControlState> with AppLogger {

loggy.app('Connectivity event: ${result.name}');

emit(state.copyWith(connectivityType: result));
emit(state.copyWith(connectivityType: result, syncOnMobile: syncOnMobile));

var newMode = NetworkMode.disabled;

Expand Down Expand Up @@ -197,8 +203,9 @@ class PowerControl extends Cubit<PowerControlState> with AppLogger {
await _setNetworkMode(newMode);
}

Future<void> _refresh() async =>
_onConnectivityChange((await _connectivity.checkConnectivity()).last);
Future<void> _refresh({bool? syncOnMobile = null}) async =>
_onConnectivityChange((await _connectivity.checkConnectivity()).last,
syncOnMobile: syncOnMobile);

Future<void> _setNetworkMode(NetworkMode mode, {force = false}) async {
if (state.networkMode == null || mode != state.networkMode || force) {
Expand Down
1 change: 0 additions & 1 deletion lib/app/cubits/repo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ class RepoCubit extends Cubit<RepoState> with AppLogger {

static Future<RepoCubit> create({
required NativeChannels nativeChannels,
required Settings settings,
required Repository repo,
required RepoLocation location,
required NavigationCubit navigation,
Expand Down
3 changes: 0 additions & 3 deletions lib/app/cubits/repos.dart
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ class ReposCubit extends WatchSelf<ReposCubit> with AppLogger {

final cubit = await RepoCubit.create(
nativeChannels: _nativeChannels,
settings: _settings,
navigation: navigation,
bottomSheet: bottomSheet,
repo: repo,
Expand Down Expand Up @@ -479,7 +478,6 @@ class ReposCubit extends WatchSelf<ReposCubit> with AppLogger {

final cubit = await RepoCubit.create(
nativeChannels: _nativeChannels,
settings: _settings,
navigation: navigation,
bottomSheet: bottomSheet,
repo: repo,
Expand Down Expand Up @@ -564,7 +562,6 @@ class ReposCubit extends WatchSelf<ReposCubit> with AppLogger {

final cubit = await RepoCubit.create(
nativeChannels: _nativeChannels,
settings: _settings,
navigation: navigation,
bottomSheet: bottomSheet,
repo: repo,
Expand Down
2 changes: 2 additions & 0 deletions lib/app/models/repo_location.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class RepoLocation implements Comparable<RepoLocation> {
RepoLocation move(io.Directory newDir) =>
RepoLocation._(newDir.path, _name, _ext);

RepoLocation clone() => RepoLocation._(this._dir, this._name, this._ext);

@override
bool operator ==(Object other) =>
other is RepoLocation && p.equals(path, other.path);
Expand Down
8 changes: 8 additions & 0 deletions lib/app/utils/settings/atomic_shared_prefs_settings_key.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// In Settings V0 we used the SharedPreferences API to set the keys and
// values, but each of these API functions (of the flutter/SharedPreferences
// version we started with) made an atomic update to the settings and thus we
// couldn't update multiple values and then commit then all at once
// atomically. Since Settings V1 we store everything in just one
// SharedPreferences key, the `atomicSharedPrefsSettingsKey`, and save/commit
// the whole thing atomically at once.
const String atomicSharedPrefsSettingsKey = "settings";
23 changes: 17 additions & 6 deletions lib/app/utils/settings/settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,33 @@ import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

import 'v1.dart' as v1;
import 'v2.dart' as v2;
import '../files.dart';
import '../log.dart';
import '../master_key.dart';

typedef DatabaseId = v1.DatabaseId;
typedef Settings = v1.Settings;
typedef DatabaseId = v2.DatabaseId;
typedef Settings = v2.Settings;

Future<Settings> loadAndMigrateSettings(Session session) async {
await _migratePaths();

final masterKey = await MasterKey.init();

final settings = await v1.Settings.init(masterKey);
await settings.migrate(session);

return settings;
try {
final settingsV2 = await v2.Settings.init(masterKey);
return settingsV2;
} on v2.InvalidSettingsVersion catch (e) {
if (e.statedVersion < 2) {
final settingsV1 = await v1.Settings.init(masterKey);
await settingsV1.migrate(session);
return await v2.Settings.initWithV1(settingsV1);
} else {
throw "Settings have been created with a newer Ouisync version and thus can't be migrated";
}
} catch (e) {
rethrow;
}
}

Future<void> _migratePaths() async {
Expand Down
64 changes: 56 additions & 8 deletions lib/app/utils/settings/v1.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import '../../models/models.dart';
import '../files.dart';
import '../master_key.dart';
import '../utils.dart';
import 'atomic_shared_prefs_settings_key.dart';
import 'v0/v0.dart' as v0;

class DatabaseId extends Equatable {
Expand Down Expand Up @@ -92,7 +93,7 @@ class SettingsRoot {
int inputVersion = data[_versionKey];

if (inputVersion != version) {
throw "Invalid settings version ($inputVersion)";
throw InvalidSettingsVersion(inputVersion);
}

final repos = {
Expand All @@ -116,8 +117,6 @@ class SettingsRoot {
}

class Settings with AppLogger {
static const String settingsKey = "settings";

final MasterKey masterKey;

final SettingsRoot _root;
Expand All @@ -128,15 +127,16 @@ class Settings with AppLogger {
Settings._(this._root, this._prefs, this.masterKey);

Future<void> _storeRoot() async {
await _prefs.setString(settingsKey, json.encode(_root.toJson()));
await _prefs.setString(
atomicSharedPrefsSettingsKey, json.encode(_root.toJson()));
}

static Future<Settings> init(
MasterKey masterKey,
) async {
final prefs = await SharedPreferences.getInstance();

final json = prefs.getString(settingsKey);
final json = prefs.getString(atomicSharedPrefsSettingsKey);
final root = SettingsRoot.fromJson(json);

return Settings._(root, prefs, masterKey);
Expand All @@ -148,8 +148,10 @@ class Settings with AppLogger {
}

Future<void> _migrateValues(Session session) async {
// Check if already fully migrated.
if (_prefs.containsKey(settingsKey) && _prefs.getKeys().length == 1) {
// Check if already fully migrated. The `atomicSharedPrefsSettingsKey` was introduced in V1
// where it's the only key.
if (_prefs.containsKey(atomicSharedPrefsSettingsKey) &&
_prefs.getKeys().length == 1) {
return;
}

Expand Down Expand Up @@ -234,7 +236,8 @@ class Settings with AppLogger {
// to do this **after** we've stored the root and version number of this
// settings.
for (final key in _prefs.getKeys()) {
if (key == settingsKey || key == v0.Settings.knownRepositoriesKey) {
if (key == atomicSharedPrefsSettingsKey ||
key == v0.Settings.knownRepositoriesKey) {
continue;
}

Expand Down Expand Up @@ -442,4 +445,49 @@ class Settings with AppLogger {
}
print("=======================================");
}

//------------------------------------------------------------------

// Only for use in migrations!
MigrationContext getMigrationContext() => MigrationContext(
masterKey: masterKey,
acceptedEqualitieValues: _root.acceptedEqualitieValues,
showOnboarding: _root.showOnboarding,
highestSeenProtocolNumber: _root.highestSeenProtocolNumber,
defaultRepo: _root.defaultRepo?.clone(),
repos: Map.from(_root.repos),
defaultRepositoriesDirVersion: _root.defaultRepositoriesDirVersion,
sharedPreferences: _prefs,
);
}

class InvalidSettingsVersion {
int statedVersion;
InvalidSettingsVersion(this.statedVersion);
@override
String toString() => "Invalid settings version ($statedVersion)";
}

class MigrationContext {
final MasterKey masterKey;
final bool acceptedEqualitieValues;
final bool showOnboarding;
// Intentionally not including this one as it's not used in V2.
//final bool enableSyncOnMobileInternet;
final int? highestSeenProtocolNumber;
final RepoLocation? defaultRepo;
final Map<DatabaseId, RepoLocation> repos;
final int defaultRepositoriesDirVersion;
final SharedPreferences sharedPreferences;

MigrationContext({
required this.masterKey,
required this.acceptedEqualitieValues,
required this.showOnboarding,
required this.highestSeenProtocolNumber,
required this.defaultRepo,
required this.repos,
required this.defaultRepositoriesDirVersion,
required this.sharedPreferences,
});
}
Loading

0 comments on commit 19b7895

Please sign in to comment.