Add user settings for network capabilities

This commit is contained in:
Hank Grabowski 2024-06-26 14:57:23 -04:00
parent 02ebaef47a
commit 2b347b5572
5 changed files with 301 additions and 0 deletions

View file

@ -0,0 +1,121 @@
import '../timeline_network_info.dart';
class NetworkCapabilitiesSettings {
late final List<NetworkCapabilitiesItem> _capabilities;
late final Map<KnownNetworks, NetworkCapabilitiesItem> _capabilitiesKV;
num get length => _capabilities.length;
NetworkCapabilitiesSettings(
{required List<NetworkCapabilitiesItem> capabilities}) {
_capabilities = capabilities;
_capabilitiesKV = {for (final c in capabilities) c.network: c};
}
NetworkCapabilitiesItem operator [](int i) => _capabilities[i];
NetworkCapabilitiesItem getCapabilities(KnownNetworks network) =>
_capabilitiesKV[network] ?? NetworkCapabilitiesItem.unknown();
operator []=(int i, NetworkCapabilitiesItem item) {
_capabilities[i] = item;
_capabilitiesKV[item.network] = item;
}
factory NetworkCapabilitiesSettings.defaultSettings() {
final networks = <KnownNetworks>{};
networks.add(KnownNetworks.friendica);
networks.add(KnownNetworks.mastodon);
networks.add(KnownNetworks.threads);
networks.add(KnownNetworks.bluesky);
networks.add(KnownNetworks.diaspora);
networks.add(KnownNetworks.pixelfed);
networks.add(KnownNetworks.peertube);
networks.add(KnownNetworks.unknown);
networks.addAll(KnownNetworks.values);
final capabilities = networks
.map((e) => switch (e) {
KnownNetworks.activityPub => NetworkCapabilitiesItem(
network: e,
react: true,
reshare: true,
comment: true,
),
KnownNetworks.bluesky => NetworkCapabilitiesItem(
network: e,
react: true,
reshare: false,
comment: true,
),
KnownNetworks.threads => NetworkCapabilitiesItem(
network: e,
react: true,
reshare: false,
comment: false,
),
_ => NetworkCapabilitiesItem(
network: e,
react: true,
reshare: true,
comment: true,
),
})
.toList();
return NetworkCapabilitiesSettings(capabilities: capabilities);
}
factory NetworkCapabilitiesSettings.fromJson(List<dynamic> json) {
final capabilities =
json.map((j) => NetworkCapabilitiesItem.fromJson(j)).toList();
return NetworkCapabilitiesSettings(capabilities: capabilities);
}
List<Map<String, dynamic>> toJson() {
return _capabilities.map((c) => c.toJson()).toList();
}
}
class NetworkCapabilitiesItem {
final KnownNetworks network;
final bool react;
final bool reshare;
final bool comment;
NetworkCapabilitiesItem({
required this.network,
required this.react,
required this.reshare,
required this.comment,
});
factory NetworkCapabilitiesItem.fromJson(Map<String, dynamic> json) =>
NetworkCapabilitiesItem(
network: KnownNetworks.parse(json['network']),
react: json['react'] ?? true,
reshare: json['reshare'] ?? true,
comment: json['comment'] ?? true,
);
factory NetworkCapabilitiesItem.unknown() => NetworkCapabilitiesItem(
network: KnownNetworks.unknown,
react: true,
reshare: true,
comment: true,
);
NetworkCapabilitiesItem copyWith(
{bool? react, bool? reshare, bool? comment}) =>
NetworkCapabilitiesItem(
network: network,
react: react ?? this.react,
reshare: reshare ?? this.reshare,
comment: comment ?? this.comment,
);
Map<String, dynamic> toJson() => {
'network': network.name,
'react': react,
'reshare': reshare,
'comment': comment,
};
}

View file

@ -23,6 +23,18 @@ enum KnownNetworks {
threads,
wordpress,
unknown,
;
static KnownNetworks parse(String? text) {
if (text == null) {
return unknown;
}
return values.firstWhere(
(e) => e.name == text,
orElse: () => unknown,
);
}
}
class TimelineNetworkInfo {

View file

@ -12,6 +12,7 @@ import '../di_initialization.dart';
import '../globals.dart';
import '../routes.dart';
import '../services/setting_service.dart';
import '../utils/known_network_extensions.dart';
import '../utils/theme_mode_extensions.dart';
class SettingsScreen extends StatelessWidget {
@ -34,6 +35,7 @@ class SettingsScreen extends StatelessWidget {
if (!kReleaseMode) buildColorBlindnessTestSettings(settings),
buildClearCaches(context),
buildLogPanel(context, settings),
const NetworkCapabilitiesWidget(),
],
),
),
@ -138,3 +140,77 @@ class SettingsScreen extends StatelessWidget {
);
}
}
class NetworkCapabilitiesWidget extends StatelessWidget {
const NetworkCapabilitiesWidget({super.key});
@override
Widget build(BuildContext context) {
final settings = context.watch<SettingsService>();
final nc = settings.networkCapabilities;
final rows = <DataRow>[];
for (int i = 0; i < nc.length; i++) {
final e = nc[i];
final r = DataRow(
cells: [
DataCell(
Text(
'${e.network.forkAwesomeUnicode} ${e.network.labelName}',
style: const TextStyle(fontFamily: 'ForkAwesome'),
),
),
DataCell(
Checkbox(
value: e.react,
onChanged: (bool? value) {
nc[i] = e.copyWith(react: value ?? false);
settings.networkCapabilities = nc;
},
),
),
DataCell(
Checkbox(
value: e.reshare,
onChanged: (bool? value) {
nc[i] = e.copyWith(reshare: value ?? false);
settings.networkCapabilities = nc;
},
),
),
DataCell(
Checkbox(
value: e.comment,
onChanged: (bool? value) {
nc[i] = e.copyWith(comment: value ?? false);
settings.networkCapabilities = nc;
},
),
),
],
);
rows.add(r);
}
return ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Network Capabilities'),
ElevatedButton(
onPressed: null,
child: Text('Reset to Defaults'),
),
],
),
subtitle: DataTable(
columns: [
DataColumn(label: Text('Network')),
DataColumn(label: Text('React')),
DataColumn(label: Text('Reshare')),
DataColumn(label: Text('Comment')),
],
rows: rows,
));
}
}

View file

@ -1,8 +1,11 @@
import 'dart:convert';
import 'package:color_blindness/color_blindness.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/settings/network_capabilities_settings.dart';
import '../utils/theme_mode_extensions.dart';
class SettingsService extends ChangeNotifier {
@ -51,6 +54,18 @@ class SettingsService extends ChangeNotifier {
notifyListeners();
}
NetworkCapabilitiesSettings _networkCapabilities =
NetworkCapabilitiesSettings.defaultSettings();
NetworkCapabilitiesSettings get networkCapabilities => _networkCapabilities;
set networkCapabilities(NetworkCapabilitiesSettings updatedCapabilities) {
_networkCapabilities = updatedCapabilities;
final jsonString = jsonEncode(_networkCapabilities.toJson());
_prefs.setString(_networkCapabilitiesKey, jsonString);
notifyListeners();
}
Future<void> initialize() async {
if (_initialized) {
return;
@ -60,6 +75,7 @@ class SettingsService extends ChangeNotifier {
_themeMode = ThemeModeExtensions.parse(_prefs.getString(_themeModeKey));
_colorBlindnessType = _colorBlindnessTypeFromPrefs(_prefs);
_logLevel = _levelFromPrefs(_prefs);
_networkCapabilities = _networkCapabilitiesFromPrefs(_prefs);
_initialized = true;
}
}
@ -68,6 +84,7 @@ const _lowBandwidthModeKey = 'LowBandwidthMode';
const _themeModeKey = 'ThemeMode';
const _colorBlindnessTestingModeKey = 'ColorBlindnessTestingMode';
const _logLevelKey = 'LogLevel';
const _networkCapabilitiesKey = 'NetworkCapabilities';
ColorBlindnessType _colorBlindnessTypeFromPrefs(SharedPreferences prefs) {
final cbString = prefs.getString(_colorBlindnessTestingModeKey);
@ -80,6 +97,18 @@ ColorBlindnessType _colorBlindnessTypeFromPrefs(SharedPreferences prefs) {
);
}
NetworkCapabilitiesSettings _networkCapabilitiesFromPrefs(
SharedPreferences prefs) {
final ncString = prefs.getString(_networkCapabilitiesKey);
if (ncString?.isEmpty ?? true) {
return NetworkCapabilitiesSettings.defaultSettings();
}
final List<dynamic> json = jsonDecode(ncString!);
final nc = NetworkCapabilitiesSettings.fromJson(json);
return nc;
}
Level _levelFromPrefs(SharedPreferences prefs) {
final levelString = prefs.getString(_logLevelKey);
return switch (levelString) {

View file

@ -0,0 +1,63 @@
import '../models/timeline_network_info.dart';
extension KnownNetworkExtensions on KnownNetworks {
String get labelName => switch (this) {
KnownNetworks.activityPub => 'ActivityPub',
KnownNetworks.bluesky => 'Bluesky',
KnownNetworks.calckey => 'Calckey',
KnownNetworks.diaspora => 'Diaspora',
KnownNetworks.drupal => 'Drupal',
KnownNetworks.firefish => 'Firefish',
KnownNetworks.friendica => 'Friendica',
KnownNetworks.funkwhale => 'Funkwhale',
KnownNetworks.gnu_social => 'GNU Social',
KnownNetworks.hubzilla => 'Hubzilla',
KnownNetworks.kbin => 'Kbin',
KnownNetworks.lemmy => 'Lemmy',
KnownNetworks.mastodon => 'Mastodon',
KnownNetworks.nextcloud => 'Nextcloud',
KnownNetworks.peertube => 'PeerTube',
KnownNetworks.pixelfed => 'Pixelfed',
KnownNetworks.pleroma => 'Pleroma',
KnownNetworks.plume => 'Plume',
KnownNetworks.red => 'Red',
KnownNetworks.redmatrix => 'RedMatrix',
KnownNetworks.socialhome => 'Socialhome',
KnownNetworks.threads => 'Threads',
KnownNetworks.wordpress => 'WordPress',
KnownNetworks.unknown => 'Unknown',
};
String get forkAwesomeUnicode => switch (this) {
KnownNetworks.activityPub => '\uf2f2',
KnownNetworks.bluesky => '\uf111',
KnownNetworks.calckey => '\uf1ec',
KnownNetworks.diaspora => '\uf2e5',
KnownNetworks.drupal => '\uf1a9',
KnownNetworks.firefish => '\uf06d',
KnownNetworks.friendica => '\uf2e6',
KnownNetworks.funkwhale => '\uf339',
KnownNetworks.gnu_social => '\uf2e7',
KnownNetworks.hubzilla => '\uf2eb',
KnownNetworks.kbin => '\uf058',
KnownNetworks.lemmy => '\uf0c0',
KnownNetworks.mastodon => '\uf2e1',
KnownNetworks.nextcloud => '\uf307',
KnownNetworks.peertube => '\uf2e4',
KnownNetworks.pixelfed => '\uf314',
KnownNetworks.pleroma => '\uf324',
KnownNetworks.plume => '\uf356',
KnownNetworks.red => '\uf2eb',
KnownNetworks.redmatrix => '\uf2eb',
KnownNetworks.socialhome => '\uf2ec',
KnownNetworks.threads => '\uf16d',
KnownNetworks.wordpress => '\uf19a',
KnownNetworks.unknown => '\uf059',
};
}
extension TimelineNetworkInfoExtensions on TimelineNetworkInfo {
String get labelName => network.labelName;
String get forkAwesomeUnicode => network.forkAwesomeUnicode;
}