Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Wip info page * Update linux_system_info to 0.0.6 * Add useful packages * Clean single_info_row code * Add many missing infos - Gpu name - Hostname - OS type - Gnome version - Window server * Move to model * Get gpu name * Get disk capacity * Move hostname to new top section * Make hostname editable * Drop unused file * Make text selectable * Move formating out of model * Make init tasks asynchronous * Move info class call to constructor * Use int for numbers * Fix terminology * Use SafeChangeNotifier * Format files * Revert sdk version
- Loading branch information
Showing
6 changed files
with
667 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import 'dart:ffi'; | ||
import 'dart:io'; | ||
|
||
import 'package:linux_system_info/linux_system_info.dart'; | ||
import 'package:safe_change_notifier/safe_change_notifier.dart'; | ||
import 'package:udisks/udisks.dart'; | ||
|
||
import 'hostname_service.dart'; | ||
|
||
class InfoModel extends SafeChangeNotifier { | ||
InfoModel( | ||
[HostnameService? hostnameService, | ||
UDisksClient? uDisksClient, | ||
List<Cpu>? cpus, | ||
SystemInfo? systemInfo, | ||
MemInfo? memInfo, | ||
GnomeInfo? gnomeInfo]) | ||
: _hostnameService = hostnameService ?? HostnameService(), | ||
_uDisksClient = uDisksClient ?? UDisksClient(), | ||
_cpus = cpus ?? CpuInfo.getProcessors(), | ||
_systemInfo = systemInfo ?? SystemInfo(), | ||
_memInfo = memInfo ?? MemInfo(), | ||
_gnomeInfo = gnomeInfo ?? GnomeInfo(); | ||
|
||
final HostnameService _hostnameService; | ||
final UDisksClient _uDisksClient; | ||
final List<Cpu> _cpus; | ||
final SystemInfo _systemInfo; | ||
final MemInfo _memInfo; | ||
final GnomeInfo _gnomeInfo; | ||
|
||
String _gpuName = ''; | ||
int? _diskCapacity; | ||
|
||
Future<void> init() async { | ||
await _hostnameService.init(); | ||
|
||
await GpuInfo.load().then((gpus) { | ||
_gpuName = gpus.first.model; | ||
}); | ||
|
||
await _uDisksClient.connect().then((value) { | ||
_diskCapacity = | ||
_uDisksClient.drives.fold<int>(0, (sum, drive) => sum + drive.size); | ||
}); | ||
|
||
notifyListeners(); | ||
} | ||
|
||
String get hostname => _hostnameService.hostname; | ||
String get staticHostname => _hostnameService.staticHostname; | ||
|
||
void setHostname(String hostname) { | ||
_hostnameService.setHostname(hostname).then((_) => notifyListeners()); | ||
} | ||
|
||
String get osName => _systemInfo.os_name; | ||
String get osVersion => _systemInfo.os_version; | ||
int get osType => sizeOf<IntPtr>() * 8; | ||
|
||
String get processorName => _cpus[0].model_name; | ||
int get processorCount => _cpus.length + 1; | ||
int get memory => _memInfo.mem_total_gb; | ||
String get graphics => _gpuName; | ||
int? get diskCapacity => _diskCapacity; | ||
|
||
String get gnomeVersion => _gnomeInfo.version; | ||
String get windowServer => Platform.environment['XDG_SESSION_TYPE'] ?? ''; | ||
|
||
@override | ||
void dispose() { | ||
_hostnameService.dispose(); | ||
_uDisksClient.close(); | ||
super.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
import 'package:filesize/filesize.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/widgets.dart'; | ||
import 'package:provider/provider.dart'; | ||
import 'package:settings/view/widgets/settings_row.dart'; | ||
import 'package:settings/view/widgets/settings_section.dart'; | ||
import 'package:settings/view/widgets/single_info_row.dart'; | ||
import 'package:yaru_icons/widgets/yaru_icons.dart'; | ||
import 'package:yaru/yaru.dart' as yaru; | ||
|
||
import 'info_model.dart'; | ||
|
||
class InfoPage extends StatefulWidget { | ||
const InfoPage({Key? key}) : super(key: key); | ||
|
||
@override | ||
_InfoPageState createState() => _InfoPageState(); | ||
} | ||
|
||
class _InfoPageState extends State<InfoPage> { | ||
@override | ||
void initState() { | ||
super.initState(); | ||
|
||
final model = context.read<InfoModel>(); | ||
model.init(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final model = context.watch<InfoModel>(); | ||
|
||
return Column( | ||
children: [ | ||
const Icon(YaruIcons.ubuntu_logo, size: 128, color: yaru.Colors.orange), | ||
const SizedBox(height: 10), | ||
Text('${model.osName} ${model.osVersion}', | ||
style: Theme.of(context).textTheme.headline5), | ||
const SizedBox(height: 30), | ||
const _Computer(), | ||
SettingsSection(headline: 'Hardware', children: [ | ||
SingleInfoRow( | ||
infoLabel: 'Processor', | ||
infoValue: '${model.processorName} x ${model.processorCount}', | ||
), | ||
SingleInfoRow( | ||
infoLabel: 'Memory', | ||
infoValue: '${model.memory} Gb', | ||
), | ||
SingleInfoRow( | ||
infoLabel: 'Graphics', | ||
infoValue: model.graphics, | ||
), | ||
SingleInfoRow( | ||
infoLabel: 'Disk Capacity', | ||
infoValue: | ||
model.diskCapacity != null ? filesize(model.diskCapacity) : '', | ||
), | ||
]), | ||
SettingsSection(headline: 'System', children: [ | ||
SingleInfoRow( | ||
infoLabel: 'OS name', | ||
infoValue: '${model.osName} ${model.osVersion}', | ||
), | ||
SingleInfoRow( | ||
infoLabel: 'OS type', | ||
infoValue: '${model.osType}-bit', | ||
), | ||
SingleInfoRow( | ||
infoLabel: 'GNOME version', | ||
infoValue: model.gnomeVersion, | ||
), | ||
SingleInfoRow( | ||
infoLabel: 'Windowing System', | ||
infoValue: model.windowServer, | ||
), | ||
]), | ||
], | ||
); | ||
} | ||
} | ||
|
||
class _Computer extends StatelessWidget { | ||
const _Computer({Key? key}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final model = Provider.of<InfoModel>(context); | ||
|
||
return SettingsSection(headline: 'Computer', children: [ | ||
SettingsRow( | ||
actionLabel: 'Hostname', | ||
secondChild: Row( | ||
children: [ | ||
SelectableText( | ||
model.hostname, | ||
style: TextStyle( | ||
color: Theme.of(context).colorScheme.onSurface.withAlpha(150), | ||
), | ||
), | ||
const SizedBox(width: 16.0), | ||
SizedBox( | ||
width: 40, | ||
height: 40, | ||
child: OutlinedButton( | ||
style: | ||
OutlinedButton.styleFrom(padding: const EdgeInsets.all(0)), | ||
onPressed: () => showDialog( | ||
context: context, | ||
builder: (_) => ChangeNotifierProvider.value( | ||
value: model, | ||
child: const _HostnameSettings(), | ||
), | ||
), | ||
child: const Icon(YaruIcons.settings), | ||
), | ||
), | ||
], | ||
), | ||
) | ||
]); | ||
} | ||
} | ||
|
||
class _HostnameSettings extends StatefulWidget { | ||
const _HostnameSettings({Key? key}) : super(key: key); | ||
|
||
@override | ||
State<_HostnameSettings> createState() => _HostnameSettingsState(); | ||
} | ||
|
||
class _HostnameSettingsState extends State<_HostnameSettings> { | ||
final _controller = TextEditingController(); | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
|
||
final model = context.read<InfoModel>(); | ||
_controller.value = TextEditingValue( | ||
text: model.hostname, | ||
selection: TextSelection.collapsed(offset: model.hostname.length), | ||
); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_controller.dispose(); | ||
super.dispose(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final model = context.watch<InfoModel>(); | ||
return SimpleDialog( | ||
title: const Center(child: Text('Edit hostname')), | ||
contentPadding: const EdgeInsets.all(16.0), | ||
children: [ | ||
TextField(controller: _controller), | ||
const SizedBox(height: 16.0), | ||
Row( | ||
mainAxisAlignment: MainAxisAlignment.end, | ||
children: [ | ||
TextButton( | ||
onPressed: () => model.setHostname(_controller.value.text), | ||
child: const Text('Rename'), | ||
) | ||
], | ||
) | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
import 'settings_row.dart'; | ||
|
||
class SingleInfoRow extends StatelessWidget { | ||
final String infoLabel; | ||
final String infoValue; | ||
|
||
const SingleInfoRow( | ||
{Key? key, required this.infoLabel, required this.infoValue}) | ||
: super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return SettingsRow( | ||
actionLabel: infoLabel, | ||
secondChild: Expanded( | ||
flex: 2, | ||
child: SelectableText( | ||
infoValue, | ||
style: TextStyle( | ||
color: Theme.of(context).colorScheme.onSurface.withAlpha(150), | ||
), | ||
textAlign: TextAlign.right | ||
) | ||
) | ||
); | ||
} | ||
} |
Oops, something went wrong.