Skip to content

Commit b08f2e1

Browse files
committed
Implement package listing
1 parent 5b7d63a commit b08f2e1

File tree

8 files changed

+330
-104
lines changed

8 files changed

+330
-104
lines changed

lib/pages/main/devices.dart

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import 'package:desktop_adb_file_browser/pages/adb_check.dart';
2+
import 'package:desktop_adb_file_browser/riverpod/selected_device.dart';
23
import 'package:desktop_adb_file_browser/routes.dart';
34
import 'package:desktop_adb_file_browser/utils/adb.dart';
45
import 'package:desktop_adb_file_browser/widgets/device_card.dart';
56
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
67
import 'package:flutter/material.dart';
8+
import 'package:flutter_riverpod/flutter_riverpod.dart';
79
import 'package:routemaster/routemaster.dart';
810

9-
class DevicesPage extends StatefulWidget {
10-
const DevicesPage(
11-
{super.key, this.serialSelector, required this.canNavigate});
11+
class DevicesPage extends ConsumerStatefulWidget {
12+
const DevicesPage({super.key, required this.canNavigate});
1213

13-
final ValueNotifier<String?>? serialSelector;
1414
final bool canNavigate;
1515

1616
@override
17-
State<DevicesPage> createState() => _DevicesPageState();
17+
ConsumerState<DevicesPage> createState() => _DevicesPageState();
1818
}
1919

20-
class _DevicesPageState extends State<DevicesPage> {
20+
class _DevicesPageState extends ConsumerState<DevicesPage> {
2121
Future<List<Device>>? _deviceListFuture;
2222

2323
@override
@@ -105,6 +105,8 @@ class _DevicesPageState extends State<DevicesPage> {
105105
}
106106

107107
Widget _deviceListView(Iterable<Device> devices) {
108+
final deviceSelector = ref.watch(selectedDeviceProvider);
109+
108110
if (devices.isEmpty) {
109111
return Center(
110112
child: Text("No devices found",
@@ -113,19 +115,23 @@ class _DevicesPageState extends State<DevicesPage> {
113115
}
114116

115117
return ListView(
116-
padding: const EdgeInsets.all(4.0),
117-
children: devices
118-
.map((e) => DeviceCard(
119-
device: e,
120-
onTap: _onDeviceSelect,
121-
showLogButton: widget.canNavigate,
122-
selected: widget.serialSelector?.value == e.serialName,
123-
))
124-
.toList(growable: false));
118+
padding: const EdgeInsets.all(4.0),
119+
children: devices
120+
.map(
121+
(e) => DeviceCard(
122+
device: e,
123+
onTap: _onDeviceSelect,
124+
showLogButton: widget.canNavigate,
125+
selected: deviceSelector?.serialName == e.serialName,
126+
),
127+
)
128+
.toList(growable: false),
129+
);
125130
}
126131

127132
void _onDeviceSelect(Device device) {
128-
widget.serialSelector?.value = device.serialName;
133+
final deviceSelector = ref.read(selectedDeviceProvider.notifier);
134+
deviceSelector.selectDevice(device);
129135

130136
if (widget.canNavigate) {
131137
Routes.browse(context, device.serialName);

lib/pages/main/package_list.dart

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,74 @@
1+
import 'package:desktop_adb_file_browser/riverpod/package_list.dart';
12
import 'package:flutter/material.dart';
3+
import 'package:flutter_riverpod/flutter_riverpod.dart';
24
import 'package:freezed_annotation/freezed_annotation.dart';
35

4-
// part 'package_list.g.dart';
5-
part 'package_list.freezed.dart';
6-
7-
@freezed
8-
class PackageMetadata with _$PackageMetadata {
9-
const factory PackageMetadata({
10-
required String packageName,
11-
required String packageId,
12-
required String version,
13-
required String groupId,
14-
}) = _PackageMetadata;
15-
}
16-
17-
class PackageList extends StatefulWidget {
6+
class PackageList extends ConsumerStatefulWidget {
187
const PackageList({super.key, required this.serial});
198

209
final String serial;
2110

2211
@override
23-
State<PackageList> createState() => _PackageListState();
12+
ConsumerState<PackageList> createState() => _PackageListState();
2413
}
2514

26-
class _PackageListState extends State<PackageList> {
27-
final packageList = [
28-
const PackageMetadata(
29-
groupId: "flamingo",
30-
packageId: "wen",
31-
packageName: "hoodie",
32-
version: "1.0.0"),
33-
const PackageMetadata(
34-
groupId: "flamingo",
35-
packageId: "wen",
36-
packageName: "hoodie",
37-
version: "1.0.0"),
38-
const PackageMetadata(
39-
groupId: "flamingo",
40-
packageId: "wen",
41-
packageName: "hoodie",
42-
version: "1.0.0"),
43-
const PackageMetadata(
44-
groupId: "flamingo",
45-
packageId: "wen",
46-
packageName: "hoodie",
47-
version: "1.0.0"),
48-
];
49-
15+
class _PackageListState extends ConsumerState<PackageList> {
5016
@override
5117
Widget build(BuildContext context) {
18+
final packageListFuture = ref.watch(packageListProvider);
19+
5220
return Scaffold(
5321
appBar: AppBar(
5422
title: const Text("Packages"),
5523
automaticallyImplyLeading: true,
5624
),
57-
body: ListView.separated(
58-
itemBuilder: itemBuilder,
59-
itemCount: packageList.length,
60-
shrinkWrap: true,
61-
separatorBuilder: (context, index) => const Divider(),
25+
body: packageListFuture.when(
26+
data: (packageList) => ListView.separated(
27+
itemBuilder: (c, i) => itemBuilder(c, i, packageList),
28+
itemCount: packageList.length,
29+
shrinkWrap: true,
30+
separatorBuilder: (context, index) => const Divider(),
31+
),
32+
error: (error, stackTrace) {
33+
debugPrint(error.toString());
34+
debugPrint(stackTrace.toString());
35+
return Center(
36+
child: Text("Error: $error"),
37+
);
38+
},
39+
loading: () => const Center(
40+
child: CircularProgressIndicator(),
41+
),
6242
),
6343
);
6444
}
6545

66-
Widget? itemBuilder(BuildContext context, int index) {
67-
final item = packageList[index];
68-
return ListTile(
69-
title: Text(item.packageName),
70-
subtitle: Text(item.packageId),
71-
leading: const Icon(Icons.apps),
72-
dense: true,
73-
onTap: () {},
74-
trailing: Wrap(
75-
children: [
76-
IconButton(onPressed: () {}, icon: const Icon(Icons.download)),
77-
IconButton(onPressed: () {}, icon: const Icon(Icons.delete)),
78-
],
46+
Widget? itemBuilder(
47+
BuildContext context, int index, List<String> packageList) {
48+
final packageId = packageList[index];
49+
final packageMetadataFuture = ref.watch(packageInfoProvider(packageId));
50+
51+
return packageMetadataFuture.when(
52+
data: (packageMetadata) => ListTile(
53+
title: Text(packageMetadata.packageName),
54+
subtitle: Text(packageMetadata.packageId),
55+
leading: const Icon(Icons.apps),
56+
dense: true,
57+
onTap: () {},
58+
trailing: Wrap(
59+
children: [
60+
IconButton(onPressed: () {}, icon: const Icon(Icons.download)),
61+
IconButton(onPressed: () {}, icon: const Icon(Icons.delete)),
62+
],
63+
),
64+
),
65+
error: (error, stackTrace) => ListTile(
66+
title: Text(packageId),
67+
subtitle: Text("Suffered error: $error"),
68+
),
69+
loading: () => ListTile(
70+
title: Text(packageId),
71+
leading: const CircularProgressIndicator(),
7972
),
8073
);
8174
}

lib/pages/main_page.dart

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import 'package:desktop_adb_file_browser/pages/main/browser.dart';
22
import 'package:desktop_adb_file_browser/pages/main/devices.dart';
33
import 'package:desktop_adb_file_browser/pages/main/logger.dart';
44
import 'package:desktop_adb_file_browser/pages/main/package_list.dart';
5+
import 'package:desktop_adb_file_browser/riverpod/selected_device.dart';
56
import 'package:flex_color_scheme/flex_color_scheme.dart';
67
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
78
import 'package:flutter/material.dart';
9+
import 'package:flutter_riverpod/flutter_riverpod.dart';
810

911
enum _Page {
1012
devices("Devices", FluentIcons.phone_48_regular, false),
@@ -22,36 +24,33 @@ enum _Page {
2224
_Page _pageForIndex(int v) =>
2325
_Page.values.firstWhere((element) => element.index == v);
2426

25-
class MainPage extends StatefulWidget {
27+
class MainPage extends ConsumerStatefulWidget {
2628
const MainPage({super.key});
2729

2830
@override
29-
State<MainPage> createState() => _MainPageState();
31+
ConsumerState<MainPage> createState() => _MainPageState();
3032
}
3133

32-
class _MainPageState extends State<MainPage> {
34+
class _MainPageState extends ConsumerState<MainPage> {
3335
_Page _currentPage = _Page.devices;
34-
final ValueNotifier<String?> _selectedDevice = ValueNotifier<String?>(null);
3536

3637
@override
3738
void initState() {
3839
super.initState();
39-
_selectedDevice.addListener(_onDeviceSelect);
4040
}
4141

4242
@override
4343
void dispose() {
4444
super.dispose();
45-
_selectedDevice.removeListener(_onDeviceSelect);
46-
_selectedDevice.dispose();
4745
}
4846

4947
void _onDeviceSelect() {
5048
setState(() {});
5149
}
5250

5351
Widget addDisabledTooltip(Widget widget) {
54-
if (_selectedDevice.value != null) return widget;
52+
final selectedDevice = ref.read(selectedDeviceProvider);
53+
if (selectedDevice != null) return widget;
5554

5655
return Tooltip(
5756
message: "No device selected",
@@ -61,12 +60,13 @@ class _MainPageState extends State<MainPage> {
6160

6261
@override
6362
Widget build(BuildContext context) {
63+
final selectedDevice = ref.watch(selectedDeviceProvider);
64+
6465
final dests = _Page.values
6566
.map((x) => NavigationRailDestination(
6667
icon: addDisabledTooltip(Icon(x.icon)),
6768
label: Text(x.name),
68-
disabled:
69-
x.requiresDevice && _selectedDevice.value == null,
69+
disabled: x.requiresDevice && selectedDevice == null,
7070
))
7171
.toList();
7272

@@ -93,23 +93,26 @@ class _MainPageState extends State<MainPage> {
9393
);
9494
}
9595

96-
Widget _buildCurrentPage(_Page p) => switch (p) {
97-
_Page.devices => DevicesPage(
98-
key: const ValueKey("devices"),
99-
serialSelector: _selectedDevice,
100-
canNavigate: false,
101-
),
102-
_Page.browser => DeviceBrowserPage(
103-
key: const ValueKey("browser"),
104-
serial: _selectedDevice.value!,
105-
),
106-
_Page.logger => LogPage(
107-
key: const ValueKey("logger"),
108-
serial: _selectedDevice.value!,
109-
),
110-
_Page.packages => PackageList(
111-
key: const ValueKey("packages"),
112-
serial: _selectedDevice.value!,
113-
),
114-
};
96+
Widget _buildCurrentPage(_Page p) {
97+
final selectedDevice = ref.watch(selectedDeviceProvider);
98+
99+
return switch (p) {
100+
_Page.devices => const DevicesPage(
101+
key: ValueKey("devices"),
102+
canNavigate: false,
103+
),
104+
_Page.browser => DeviceBrowserPage(
105+
key: const ValueKey("browser"),
106+
serial: selectedDevice!.serialName,
107+
),
108+
_Page.logger => LogPage(
109+
key: const ValueKey("logger"),
110+
serial: selectedDevice!.serialName,
111+
),
112+
_Page.packages => PackageList(
113+
key: const ValueKey("packages"),
114+
serial: selectedDevice!.serialName,
115+
),
116+
};
117+
}
115118
}

lib/riverpod/package_list.dart

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import 'dart:collection';
2+
3+
import 'package:desktop_adb_file_browser/riverpod/selected_device.dart';
4+
import 'package:desktop_adb_file_browser/utils/adb.dart';
5+
import 'package:desktop_adb_file_browser/utils/stack.dart';
6+
import 'package:freezed_annotation/freezed_annotation.dart';
7+
import 'package:riverpod_annotation/riverpod_annotation.dart';
8+
import 'package:trace/trace.dart';
9+
10+
part 'package_list.g.dart';
11+
part 'package_list.freezed.dart';
12+
13+
@freezed
14+
class PackageMetadata with _$PackageMetadata {
15+
const factory PackageMetadata({
16+
required String packageName,
17+
required String packageId,
18+
required String version,
19+
required String groupId,
20+
}) = _PackageMetadata;
21+
}
22+
23+
@riverpod
24+
class PackageList extends _$PackageList {
25+
@override
26+
Future<List<String>> build() async {
27+
final serial = ref.watch(selectedDeviceProvider);
28+
29+
return Adb.getPackageList(serial?.serialName);
30+
}
31+
32+
void installToDevice(String path) {}
33+
34+
void deletePackage(String id) {}
35+
}
36+
37+
@riverpod
38+
Future<PackageMetadata> packageInfo(PackageInfoRef ref, String id) async {
39+
final device = ref.watch(selectedDeviceProvider);
40+
41+
return PackageMetadata(
42+
packageId: id,
43+
groupId: "",
44+
packageName: "",
45+
version: "",
46+
);
47+
}
File renamed without changes.

0 commit comments

Comments
 (0)