feat: add persistence v3

This commit is contained in:
Tien Do Nam
2026-08-02 01:11:18 +02:00
parent 94082b3048
commit 9028de152c
5 changed files with 77 additions and 65 deletions
@@ -0,0 +1,5 @@
enum QuickSaveMode {
off,
on,
paired, // only accept from favorites automatically
}
+7 -14
View File
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/color_mode.dart';
import 'package:localsend_app/model/persistence/favorite_device.dart';
import 'package:localsend_app/model/persistence/quick_save_mode.dart';
import 'package:localsend_app/model/persistence/receive_history_entry.dart';
import 'package:localsend_app/model/send_mode.dart';
import 'package:localsend_app/provider/window_dimensions_provider.dart';
@@ -78,8 +79,7 @@ const _multicastGroupKey = 'ls_multicast_group';
const _destinationKey = 'ls_destination';
const _saveToGallery = 'ls_save_to_gallery';
const _saveToHistory = 'ls_save_to_history';
const _quickSave = 'ls_quick_save';
const _quickSaveFromFavorites = 'ls_quick_save_from_favorites';
const _quickSave = 'ls_quick_save'; // a QuickSaveMode; was a bool until storage version 2 ('ls_quick_save_from_favorites' is merged into this key)
const _receivePin = 'ls_receive_pin';
const _autoFinish = 'ls_auto_finish';
const _minimizeToTray = 'ls_minimize_to_tray';
@@ -411,20 +411,13 @@ class PersistenceService {
await _prefs.setBool(_advancedSettingsKey, isEnabled);
}
bool isQuickSave() {
return _prefs.getBool(_quickSave) ?? false;
QuickSaveMode getQuickSave() {
final value = _prefs.getString(_quickSave);
return QuickSaveMode.values.firstWhereOrNull((mode) => mode.name == value) ?? QuickSaveMode.paired;
}
Future<void> setQuickSave(bool quickSave) async {
await _prefs.setBool(_quickSave, quickSave);
}
bool isQuickSaveFromFavorites() {
return _prefs.getBool(_quickSaveFromFavorites) ?? false;
}
Future<void> setQuickSaveFromFavorites(bool quickSaveFromFavorites) async {
await _prefs.setBool(_quickSaveFromFavorites, quickSaveFromFavorites);
Future<void> setQuickSave(QuickSaveMode mode) async {
await _prefs.setString(_quickSave, mode.name);
}
String? getReceivePin() {
@@ -1,13 +1,15 @@
part of 'persistence_provider.dart';
const _latestVersion = 2;
const _latestVersion = 3;
Future<void> _runMigrations(int from) async {
switch (from) {
case 1:
await _migrate2();
await SharedPreferencesStorePlatform.instance.setValue('Int', 'flutter.$_version', 2);
break;
if (from < 2) {
await _migrate2();
await SharedPreferencesStorePlatform.instance.setValue('Int', 'flutter.$_version', 2);
}
if (from < 3) {
await _migrate3();
await SharedPreferencesStorePlatform.instance.setValue('Int', 'flutter.$_version', 3);
}
}
@@ -33,3 +35,17 @@ Future<void> _migrate2() async {
}
}
}
Future<void> _migrate3() async {
_logger.info('Migrating to version 3');
final prefs = await SharedPreferencesStorePlatform.instance.getAll();
// ls_quick_save becomes a QuickSaveMode: keep "on" if it was enabled, otherwise apply the new default "paired"
// (which is what ls_quick_save_from_favorites used to do)
final quickSave = prefs['flutter.$_quickSave'] == true ? QuickSaveMode.on : QuickSaveMode.paired;
await SharedPreferencesStorePlatform.instance.setValue('String', 'flutter.$_quickSave', quickSave.name);
await SharedPreferencesStorePlatform.instance.remove('flutter.ls_quick_save_from_favorites');
// some users disabled HTTPS for performance reasons which no longer apply since the Rust migration
await SharedPreferencesStorePlatform.instance.setValue('Bool', 'flutter.$_https', true);
}
+25 -8
View File
@@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:localsend_app/gen/strings.g.dart';
import 'package:localsend_app/model/persistence/color_mode.dart';
import 'package:localsend_app/model/persistence/quick_save_mode.dart';
import 'package:localsend_app/model/send_mode.dart';
import 'package:localsend_app/model/state/settings_state.dart';
import 'package:localsend_app/provider/persistence_provider.dart';
@@ -56,8 +57,8 @@ class SettingsService extends PureNotifier<SettingsState> {
destination: _persistence.getDestination(),
saveToGallery: _persistence.isSaveToGallery(),
saveToHistory: _persistence.isSaveToHistory(),
quickSave: _persistence.isQuickSave(),
quickSaveFromFavorites: _persistence.isQuickSaveFromFavorites(),
quickSave: _persistence.getQuickSave() == QuickSaveMode.on,
quickSaveFromFavorites: _persistence.getQuickSave() == QuickSaveMode.paired,
receivePin: _persistence.getReceivePin(),
autoFinish: _persistence.isAutoFinish(),
minimizeToTray: _persistence.isMinimizeToTray(),
@@ -164,16 +165,32 @@ class SettingsService extends PureNotifier<SettingsState> {
}
Future<void> setQuickSave(bool quickSave) async {
await _persistence.setQuickSave(quickSave);
state = state.copyWith(
quickSave: quickSave,
);
final old = _persistence.getQuickSave();
final QuickSaveMode mode;
if (quickSave) {
mode = QuickSaveMode.on;
} else {
mode = old == QuickSaveMode.on ? QuickSaveMode.off : old;
}
await _setQuickSaveMode(mode);
}
Future<void> setQuickSaveFromFavorites(bool quickSaveFromFavorites) async {
await _persistence.setQuickSaveFromFavorites(quickSaveFromFavorites);
final old = _persistence.getQuickSave();
final QuickSaveMode mode;
if (quickSaveFromFavorites) {
mode = QuickSaveMode.paired;
} else {
mode = old == QuickSaveMode.paired ? QuickSaveMode.off : old;
}
await _setQuickSaveMode(mode);
}
Future<void> _setQuickSaveMode(QuickSaveMode mode) async {
await _persistence.setQuickSave(mode);
state = state.copyWith(
quickSaveFromFavorites: quickSaveFromFavorites,
quickSave: mode == QuickSaveMode.on,
quickSaveFromFavorites: mode == QuickSaveMode.paired,
);
}
+18 -37
View File
@@ -9,14 +9,15 @@ import 'package:flutter/material.dart' as _i8;
import 'package:localsend_app/gen/strings.g.dart' as _i10;
import 'package:localsend_app/model/persistence/color_mode.dart' as _i9;
import 'package:localsend_app/model/persistence/favorite_device.dart' as _i6;
import 'package:localsend_app/model/persistence/quick_save_mode.dart' as _i11;
import 'package:localsend_app/model/persistence/receive_history_entry.dart' as _i5;
import 'package:localsend_app/model/send_mode.dart' as _i11;
import 'package:localsend_app/model/send_mode.dart' as _i12;
import 'package:localsend_app/provider/persistence_provider.dart' as _i3;
import 'package:localsend_isolates/model/device.dart' as _i12;
import 'package:localsend_isolates/model/device.dart' as _i13;
import 'package:localsend_isolates/model/stored_security_context.dart' as _i2;
import 'package:mockito/mockito.dart' as _i1;
import 'package:mockito/src/dummies.dart' as _i7;
import 'package:shared_preferences/shared_preferences.dart' as _i13;
import 'package:shared_preferences/shared_preferences.dart' as _i14;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@@ -383,38 +384,18 @@ class MockPersistenceService extends _i1.Mock implements _i3.PersistenceService
as _i4.Future<void>);
@override
bool isQuickSave() =>
_i11.QuickSaveMode getQuickSave() =>
(super.noSuchMethod(
Invocation.method(#isQuickSave, []),
returnValue: false,
returnValueForMissingStub: false,
Invocation.method(#getQuickSave, []),
returnValue: _i11.QuickSaveMode.off,
returnValueForMissingStub: _i11.QuickSaveMode.off,
)
as bool);
as _i11.QuickSaveMode);
@override
_i4.Future<void> setQuickSave(bool? quickSave) =>
_i4.Future<void> setQuickSave(_i11.QuickSaveMode? mode) =>
(super.noSuchMethod(
Invocation.method(#setQuickSave, [quickSave]),
returnValue: _i4.Future<void>.value(),
returnValueForMissingStub: _i4.Future<void>.value(),
)
as _i4.Future<void>);
@override
bool isQuickSaveFromFavorites() =>
(super.noSuchMethod(
Invocation.method(#isQuickSaveFromFavorites, []),
returnValue: false,
returnValueForMissingStub: false,
)
as bool);
@override
_i4.Future<void> setQuickSaveFromFavorites(bool? quickSaveFromFavorites) =>
(super.noSuchMethod(
Invocation.method(#setQuickSaveFromFavorites, [
quickSaveFromFavorites,
]),
Invocation.method(#setQuickSave, [mode]),
returnValue: _i4.Future<void>.value(),
returnValueForMissingStub: _i4.Future<void>.value(),
)
@@ -484,16 +465,16 @@ class MockPersistenceService extends _i1.Mock implements _i3.PersistenceService
as _i4.Future<void>);
@override
_i11.SendMode getSendMode() =>
_i12.SendMode getSendMode() =>
(super.noSuchMethod(
Invocation.method(#getSendMode, []),
returnValue: _i11.SendMode.single,
returnValueForMissingStub: _i11.SendMode.single,
returnValue: _i12.SendMode.single,
returnValueForMissingStub: _i12.SendMode.single,
)
as _i11.SendMode);
as _i12.SendMode);
@override
_i4.Future<void> setSendMode(_i11.SendMode? mode) =>
_i4.Future<void> setSendMode(_i12.SendMode? mode) =>
(super.noSuchMethod(
Invocation.method(#setSendMode, [mode]),
returnValue: _i4.Future<void>.value(),
@@ -574,7 +555,7 @@ class MockPersistenceService extends _i1.Mock implements _i3.PersistenceService
as bool);
@override
_i4.Future<void> setDeviceType(_i12.DeviceType? deviceType) =>
_i4.Future<void> setDeviceType(_i13.DeviceType? deviceType) =>
(super.noSuchMethod(
Invocation.method(#setDeviceType, [deviceType]),
returnValue: _i4.Future<void>.value(),
@@ -604,7 +585,7 @@ class MockPersistenceService extends _i1.Mock implements _i3.PersistenceService
/// A class which mocks [SharedPreferences].
///
/// See the documentation for Mockito's code generation for more information.
class MockSharedPreferences extends _i1.Mock implements _i13.SharedPreferences {
class MockSharedPreferences extends _i1.Mock implements _i14.SharedPreferences {
@override
Set<String> getKeys() =>
(super.noSuchMethod(