Skip to content

Commit

Permalink
SecurityPage: add security pages (#269)
Browse files Browse the repository at this point in the history
  • Loading branch information
Feichtmeier authored Feb 17, 2022
1 parent 1eb7d4e commit 0a45e3d
Show file tree
Hide file tree
Showing 15 changed files with 686 additions and 0 deletions.
4 changes: 4 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:settings/app.dart';
import 'package:settings/schemas/schemas.dart';
import 'package:settings/services/bluetooth_service.dart';
import 'package:settings/services/hostname_service.dart';
import 'package:settings/services/house_keeping_service.dart';
import 'package:settings/services/input_source_service.dart';
import 'package:settings/services/power_profile_service.dart';
import 'package:settings/services/power_settings_service.dart';
Expand Down Expand Up @@ -64,6 +65,9 @@ void main() async {
),
Provider<InputSourceService>(
create: (_) => InputSourceService(),
),
Provider<HouseKeepingService>(
create: (_) => HouseKeepingService(),
)
],
child: const UbuntuSettingsApp(),
Expand Down
4 changes: 4 additions & 0 deletions lib/schemas/schemas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ const String schemaBackground = 'org.gnome.desktop.background';
const String schemaMutter = 'org.gnome.mutter';
const schemaSettingsDaemonPowerPlugin =
'org.gnome.settings-daemon.plugins.power';
const schemaPrivacy = 'org.gnome.desktop.privacy';
const schemaLocation = 'org.gnome.system.location';
const schemaScreenSaver = 'org.gnome.desktop.screensaver';
const schemaSession = 'org.gnome.desktop.session';
40 changes: 40 additions & 0 deletions lib/services/house_keeping_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'dart:async';

import 'package:dbus/dbus.dart';

const kHouseKeepingInterface = 'org.gnome.SettingsDaemon.Housekeeping';
const kHouseKeepingPath = '/org/gnome/SettingsDaemon/Housekeeping';
const kEmptyTrashMethodName = 'EmptyTrash';
const kRemoveTempFiles = 'RemoveTempFiles';

class HouseKeepingService {
final DBusRemoteObject _object;

HouseKeepingService() : _object = _createObject();

static DBusRemoteObject _createObject() {
return DBusRemoteObject(
DBusClient.session(),
name: kHouseKeepingInterface,
path: DBusObjectPath(kHouseKeepingPath),
);
}

Future<void> dispose() async {
await _object.client.close();
}

void emptyTrash() => _object.emptyTrash();

void removeTempFiles() => _object.removeTempFiles();
}

extension _HouseKeepingObject on DBusRemoteObject {
Future<DBusMethodSuccessResponse> emptyTrash() {
return callMethod(kHouseKeepingInterface, kEmptyTrashMethodName, []);
}

Future<DBusMethodSuccessResponse> removeTempFiles() {
return callMethod(kHouseKeepingInterface, kRemoveTempFiles, []);
}
}
5 changes: 5 additions & 0 deletions lib/view/pages/page_items.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:settings/view/pages/mouse_and_touchpad/mouse_and_touchpad_page.d
import 'package:settings/view/pages/multitasking/multi_tasking_page.dart';
import 'package:settings/view/pages/notifications/notifications_page.dart';
import 'package:settings/view/pages/power/power_page.dart';
import 'package:settings/view/pages/privacy/privacy_page.dart';
import 'package:settings/view/pages/removable_media/removable_media_page.dart';
import 'package:settings/view/pages/sound/sound_page.dart';
import 'package:settings/view/pages/wallpaper/wallpaper_page.dart';
Expand Down Expand Up @@ -37,6 +38,10 @@ final pageItems = <YaruPageItem>[
iconData: YaruIcons.desktop_panel_look,
builder: AppearancePage.create,
),
const YaruPageItem(
title: 'Privacy',
builder: PrivacyPage.create,
iconData: YaruIcons.shield),
const YaruPageItem(
title: 'Multi-tasking',
builder: MultiTaskingPage.create,
Expand Down
21 changes: 21 additions & 0 deletions lib/view/pages/privacy/connectivity_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import 'package:nm/nm.dart';
import 'package:safe_change_notifier/safe_change_notifier.dart';

class ConnectivityModel extends SafeChangeNotifier {
final NetworkManagerClient _client;

Future<void> init() {
final network = _client.connect();
return Future.wait([network]);
}

ConnectivityModel(NetworkManagerClient client) : _client = client;

bool? get checkConnectiviy => _client.connectivityCheckEnabled;
set checkConnectiviy(bool? value) {
if (value == null) return;
_client
.setConnectivityCheckEnabled(value)
.then((value) => notifyListeners());
}
}
40 changes: 40 additions & 0 deletions lib/view/pages/privacy/connectivity_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import 'package:nm/nm.dart';
import 'package:provider/provider.dart';
import 'package:settings/constants.dart';
import 'package:settings/view/pages/privacy/connectivity_model.dart';
import 'package:yaru_widgets/yaru_widgets.dart';

class ConnectivityPage extends StatefulWidget {
const ConnectivityPage({Key? key}) : super(key: key);

static Widget create(BuildContext context) => ChangeNotifierProvider(
create: (_) => ConnectivityModel(context.read<NetworkManagerClient>()),
child: const ConnectivityPage());

@override
State<ConnectivityPage> createState() => _ConnectivityPageState();
}

class _ConnectivityPageState extends State<ConnectivityPage> {
@override
void initState() {
final model = context.read<ConnectivityModel>();
model.init();
super.initState();
}

@override
Widget build(BuildContext context) {
final model = context.watch<ConnectivityModel>();
return YaruPage(children: [
YaruSwitchRow(
width: kDefaultWidth,
enabled: model.checkConnectiviy != null,
trailingWidget: const Text('Check Connectivity'),
value: model.checkConnectiviy,
onChanged: (v) => model.checkConnectiviy = v,
)
]);
}
}
199 changes: 199 additions & 0 deletions lib/view/pages/privacy/house_keeping_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:settings/constants.dart';
import 'package:settings/services/house_keeping_service.dart';
import 'package:settings/services/settings_service.dart';
import 'package:settings/view/pages/privacy/privacy_model.dart';
import 'package:yaru_icons/yaru_icons.dart';
import 'package:yaru_widgets/yaru_widgets.dart';

class HouseKeepingPage extends StatelessWidget {
const HouseKeepingPage({Key? key}) : super(key: key);

static Widget create(BuildContext context) => ChangeNotifierProvider(
create: (_) => PrivacyModel(context.read<SettingsService>(),
context.read<HouseKeepingService>()),
child: const HouseKeepingPage(),
);

@override
Widget build(BuildContext context) {
final model = context.watch<PrivacyModel>();
return YaruPage(children: [
YaruSection(
width: kDefaultWidth,
headline: 'Recent Files History',
children: [
YaruSwitchRow(
enabled: model.rememberRecentFiles != null,
trailingWidget: const Text('Remember recent files'),
value: model.rememberRecentFiles,
onChanged: (value) => model.rememberRecentFiles = value,
),
if (model.rememberRecentFiles != null &&
model.rememberRecentFiles == true)
YaruSwitchRow(
enabled: model.recentFilesMaxAge != null,
trailingWidget: const Text('Remember recent files forever'),
value: model.recentFilesMaxAge?.toDouble() == -1,
onChanged: (value) {
final intValue = value ? -1 : 1;
return model.recentFilesMaxAge = intValue;
}),
if (model.recentFilesMaxAge != null &&
model.recentFilesMaxAge?.toDouble() != -1 &&
model.rememberRecentFiles != null &&
model.rememberRecentFiles == true)
YaruSliderRow(
enabled: model.recentFilesMaxAge != null,
actionLabel: 'Days recorded',
value: model.recentFilesMaxAge?.toDouble() == -1
? -1
: model.recentFilesMaxAge?.toDouble(),
min: -1,
max: 30,
onChanged: (value) => model.recentFilesMaxAge = value.toInt())
],
),
YaruSection(
width: kDefaultWidth,
headline: 'Trash & Temp Files',
children: [
YaruSwitchRow(
enabled: model.removeOldTempFiles != null,
trailingWidget: const Text('Auto-remove old temp files'),
value: model.removeOldTempFiles,
onChanged: (value) => model.removeOldTempFiles = value,
),
YaruSwitchRow(
enabled: model.removeOldTrashFiles != null,
trailingWidget: const Text('Auto-remove old trash files'),
value: model.removeOldTrashFiles,
onChanged: (value) => model.removeOldTrashFiles = value,
),
if (model.oldFilesAge != null && model.oldFilesAge?.toDouble() != -1)
YaruSliderRow(
enabled: model.oldFilesAge != null,
actionLabel: 'Days until auto-delete',
value: model.oldFilesAge?.toDouble() == -1
? -1
: model.oldFilesAge?.toDouble(),
min: 0,
max: 30,
onChanged: (value) => model.oldFilesAge = value.toInt()),
YaruRow(
trailingWidget: const Text('Clean the house'),
actionWidget: Row(
children: [
OutlinedButton(
onPressed: () => showDialog(
context: context,
builder: (context) => _ConfirmationDialog(
title: 'Empty trash',
iconData: YaruIcons.trash_full,
onConfirm: () {
model.emptyTrash();
Navigator.of(context).pop();
},
),
),
child: Text('Empty Trash',
style:
TextStyle(color: Theme.of(context).errorColor))),
const SizedBox(
width: 10,
),
OutlinedButton(
onPressed: () => showDialog(
context: context,
builder: (context) => _ConfirmationDialog(
title: 'Remove Temp Files',
iconData: YaruIcons.document,
onConfirm: () {
model.removeTempFiles();
Navigator.of(context).pop();
},
),
),
child: Text('Remove Temp Files',
style:
TextStyle(color: Theme.of(context).errorColor))),
],
),
enabled: true)
],
),
]);
}
}

class _ConfirmationDialog extends StatefulWidget {
const _ConfirmationDialog({
Key? key,
this.onConfirm,
required this.iconData,
this.title,
}) : super(key: key);

final Function()? onConfirm;
final IconData iconData;
final String? title;

@override
State<_ConfirmationDialog> createState() => _ConfirmationDialogState();
}

class _ConfirmationDialogState extends State<_ConfirmationDialog>
with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation sizeAnimation;
late Animation colorAnimation;

@override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: const Duration(seconds: 2));
sizeAnimation = Tween<double>(begin: 100.0, end: 400.0).animate(controller);
colorAnimation =
ColorTween(begin: Colors.red, end: Colors.red.withOpacity(0.2))
.animate(controller);
controller.addListener(() {
setState(() {});
});
controller.repeat();
}

@override
void dispose() {
controller.stop();
super.dispose();
}

@override
Widget build(BuildContext context) {
return AlertDialog(
titlePadding: EdgeInsets.zero,
title: YaruDialogTitle(
title: widget.title,
),
content: Icon(
widget.iconData,
size: 100,
color: colorAnimation.value,
),
contentPadding: const EdgeInsets.only(top: 20, bottom: 50),
actions: [
OutlinedButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Cancel')),
OutlinedButton(
onPressed: widget.onConfirm,
child: Text(
'Confirm',
style: TextStyle(color: Theme.of(context).errorColor),
))
],
);
}
}
27 changes: 27 additions & 0 deletions lib/view/pages/privacy/location_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import 'package:safe_change_notifier/safe_change_notifier.dart';
import 'package:settings/schemas/schemas.dart';
import 'package:settings/services/settings_service.dart';

const _enabledKey = 'enabled';

class LocationModel extends SafeChangeNotifier {
final Settings? _locationSettings;

LocationModel(SettingsService service)
: _locationSettings = service.lookup(schemaLocation) {
_locationSettings?.addListener(notifyListeners);
}

bool? get enabled => _locationSettings?.getValue(_enabledKey);
set enabled(bool? value) {
if (value == null) return;
_locationSettings?.setValue(_enabledKey, value);
notifyListeners();
}

@override
void dispose() {
_locationSettings?.removeListener(notifyListeners);
super.dispose();
}
}
Loading

0 comments on commit 0a45e3d

Please sign in to comment.