Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[shared_preferences] Convert macOS to Pigeon #6914

Merged
merged 7 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## NEXT
## 2.0.5

* Converts platform channel to Pigeon.
* Updates code for `no_leading_underscores_for_local_identifiers` lint.
* Updates minimum Flutter version to 2.10.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,85 +4,55 @@

import FlutterMacOS
import XCTest
import shared_preferences_macos
@testable import shared_preferences_macos

class RunnerTests: XCTestCase {
func testHandlesCommitNoOp() throws {
func testSetAndGet() throws {
let plugin = SharedPreferencesPlugin()
let call = FlutterMethodCall(methodName: "commit", arguments: nil)
var called = false
plugin.handle(
call,
result: { (result: Any?) -> Void in
called = true
XCTAssert(result as? Bool == true)
})
XCTAssert(called)

plugin.setBool(key: "flutter.aBool", value: true)
plugin.setDouble(key: "flutter.aDouble", value: 3.14)
plugin.setValue(key: "flutter.anInt", value: 42)
plugin.setValue(key: "flutter.aString", value: "hello world")
plugin.setValue(key: "flutter.aStringList", value: ["hello", "world"])

let storedValues = plugin.getAll()
XCTAssertEqual(storedValues["flutter.aBool"] as? Bool, true)
XCTAssertEqual(storedValues["flutter.aDouble"] as! Double, 3.14, accuracy: 0.0001)
XCTAssertEqual(storedValues["flutter.anInt"] as? Int, 42)
XCTAssertEqual(storedValues["flutter.aString"] as? String, "hello world")
XCTAssertEqual(storedValues["flutter.aStringList"] as? Array<String>, ["hello", "world"])
}

func testSetAndGet() throws {
func testRemove() throws {
let plugin = SharedPreferencesPlugin()
let setCall = FlutterMethodCall(
methodName: "setInt",
arguments: [
"key": "flutter.foo",
"value": 42,
])
plugin.handle(
setCall,
result: { (result: Any?) -> Void in
XCTAssert(result as? Bool == true)
})
let testKey = "flutter.foo"
plugin.setValue(key: testKey, value: 42)

// Make sure there is something to remove, so the test can't pass due to a set failure.
let preRemovalValues = plugin.getAll()
XCTAssertEqual(preRemovalValues[testKey] as? Int, 42)

// Then verify that removing it works.
plugin.remove(key: testKey)

var value: Int?
plugin.handle(
FlutterMethodCall(methodName: "getAll", arguments: nil),
result: { (result: Any?) -> Void in
if let prefs = result as? [String: Any] {
value = prefs["flutter.foo"] as? Int
}
})
XCTAssertEqual(value, 42)
let finalValues = plugin.getAll()
XCTAssertNil(finalValues[testKey] as Any?)
}

func testClear() throws {
let plugin = SharedPreferencesPlugin()
let setCall = FlutterMethodCall(
methodName: "setInt",
arguments: [
"key": "flutter.foo",
"value": 42,
])
plugin.handle(setCall, result: { (result: Any?) -> Void in })
let testKey = "flutter.foo"
plugin.setValue(key: testKey, value: 42)

// Make sure there is something to clear, so the test can't pass due to a set failure.
let getCall = FlutterMethodCall(methodName: "getAll", arguments: nil)
var value: Int?
plugin.handle(
getCall,
result: { (result: Any?) -> Void in
if let prefs = result as? [String: Any] {
value = prefs["flutter.foo"] as? Int
}
})
XCTAssertEqual(value, 42)
let preRemovalValues = plugin.getAll()
XCTAssertEqual(preRemovalValues[testKey] as? Int, 42)

// Clear the value.
plugin.handle(
FlutterMethodCall(methodName: "clear", arguments: nil),
result: { (result: Any?) -> Void in
XCTAssert(result as? Bool == true)
})
// Then verify that clearing works.
plugin.clear()

// Get the value again, which should clear |value|.
plugin.handle(
getCall,
result: { (result: Any?) -> Void in
if let prefs = result as? [String: Any] {
value = prefs["flutter.foo"] as? Int
XCTAssert(prefs.isEmpty)
}
})
XCTAssertEqual(value, nil)
let finalValues = plugin.getAll()
XCTAssertNil(finalValues[testKey] as Any?)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Autogenerated from Pigeon (v5.0.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;

import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';

class UserDefaultsApi {
/// Constructor for [UserDefaultsApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
UserDefaultsApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;

static const MessageCodec<Object?> codec = StandardMessageCodec();

Future<void> remove(String arg_key) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.UserDefaultsApi.remove', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_key]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}

Future<void> setBool(String arg_key, bool arg_value) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.UserDefaultsApi.setBool', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_key, arg_value]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}

Future<void> setDouble(String arg_key, double arg_value) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.UserDefaultsApi.setDouble', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_key, arg_value]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}

Future<void> setValue(String arg_key, Object arg_value) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.UserDefaultsApi.setValue', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList =
await channel.send(<Object?>[arg_key, arg_value]) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}

Future<Map<String?, Object?>> getAll() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.UserDefaultsApi.getAll', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyList[0] as Map<Object?, Object?>?)!.cast<String?, Object?>();
}
}

Future<void> clear() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.UserDefaultsApi.clear', codec,
binaryMessenger: _binaryMessenger);
final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else {
return;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,66 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:flutter/services.dart';
import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart';
import 'messages.g.dart';

const MethodChannel _kChannel =
MethodChannel('plugins.flutter.io/shared_preferences_macos');
typedef _Setter = Future<void> Function(String key, Object value);

/// The macOS implementation of [SharedPreferencesStorePlatform].
///
/// This class implements the `package:shared_preferences` functionality for macOS.
/// macOS implementation of shared_preferences.
class SharedPreferencesMacOS extends SharedPreferencesStorePlatform {
/// Registers this class as the default instance of [SharedPreferencesStorePlatform].
final UserDefaultsApi _api = UserDefaultsApi();
late final Map<String, _Setter> _setters = <String, _Setter>{
'Bool': (String key, Object value) {
return _api.setBool(key, value as bool);
},
'Double': (String key, Object value) {
return _api.setDouble(key, value as double);
},
'Int': (String key, Object value) {
return _api.setValue(key, value as int);
},
'String': (String key, Object value) {
return _api.setValue(key, value as String);
},
'StringList': (String key, Object value) {
return _api.setValue(key, value as List<String?>);
},
};

/// Registers this class as the default instance of
/// [SharedPreferencesStorePlatform].
static void registerWith() {
SharedPreferencesStorePlatform.instance = SharedPreferencesMacOS();
}

@override
Future<bool> remove(String key) async {
return (await _kChannel.invokeMethod<bool>(
'remove',
<String, dynamic>{'key': key},
))!;
Future<bool> clear() async {
await _api.clear();
return true;
}

@override
Future<bool> setValue(String valueType, String key, Object value) async {
return (await _kChannel.invokeMethod<bool>(
'set$valueType',
<String, dynamic>{'key': key, 'value': value},
))!;
Future<Map<String, Object>> getAll() async {
final Map<String?, Object?> result = await _api.getAll();
return result.cast<String, Object>();
}

@override
Future<bool> clear() async {
return (await _kChannel.invokeMethod<bool>('clear'))!;
Future<bool> remove(String key) async {
await _api.remove(key);
return true;
}

@override
Future<Map<String, Object>> getAll() async {
final Map<String, Object>? preferences =
await _kChannel.invokeMapMethod<String, Object>('getAll');

if (preferences == null) {
return <String, Object>{};
Future<bool> setValue(String valueType, String key, Object value) async {
final _Setter? setter = _setters[valueType];
if (setter == null) {
throw PlatformException(
code: 'InvalidOperation',
message: '"$valueType" is not a supported type.');
}
return preferences;
await setter(key, value);
return true;
}
}
Loading