Add gitlab issue/merge request templates
[apps/flutter-ics-homescreen.git] / lib / data / data_providers / app_launcher.dart
1 import 'package:flutter_ics_homescreen/export.dart';
2 import 'package:protos/applauncher-api.dart';
3 import 'package:protos/agl-shell-api.dart';
4
5 class AppLauncher {
6   final Ref ref;
7
8   late ClientChannel aglShellChannel;
9   late AglShellManagerServiceClient aglShell;
10   late ClientChannel appLauncherChannel;
11   late AppLauncherClient appLauncher;
12
13   List<String> appStack = ['homescreen'];
14
15   AppLauncher({required this.ref}) {
16     aglShellChannel = ClientChannel('localhost',
17         port: 14005,
18         options: ChannelOptions(credentials: ChannelCredentials.insecure()));
19
20     aglShell = AglShellManagerServiceClient(aglShellChannel);
21
22     appLauncherChannel = ClientChannel('localhost',
23         port: 50052,
24         options: ChannelOptions(credentials: ChannelCredentials.insecure()));
25     appLauncher = AppLauncherClient(appLauncherChannel);
26   }
27
28   run() async {
29     getAppList();
30
31     try {
32       var response = appLauncher.getStatusEvents(StatusRequest());
33       await for (var event in response) {
34         if (event.hasApp()) {
35           AppStatus app_status = event.app;
36           debugPrint("Got app status:");
37           debugPrint("$app_status");
38           if (app_status.hasId() && app_status.hasStatus()) {
39             if (app_status.status == "started") {
40               activateApp(app_status.id);
41             } else if (app_status.status == "terminated") {
42               deactivateApp(app_status.id);
43             }
44           }
45         }
46       }
47     } catch (e) {
48       print(e);
49     }
50   }
51
52   getAppList() async {
53     try {
54       var response = await appLauncher.listApplications(ListRequest());
55       List<AppLauncherInfo> apps = [];
56       for (AppInfo info in response.apps) {
57         debugPrint("Got app:");
58         debugPrint("$info");
59         // Existing icons are currently not usable, so leave blank for now
60         apps.add(AppLauncherInfo(
61             id: info.id, name: info.name, icon: "", internal: false));
62       }
63       apps.sort((a, b) => a.name.compareTo(b.name));
64
65       // Add built-in app widgets
66       apps.insert(
67           0,
68           AppLauncherInfo(
69               id: "clock", name: "Clock", icon: "clock.svg", internal: true));
70       apps.insert(
71           0,
72           AppLauncherInfo(
73               id: "weather",
74               name: "Weather",
75               icon: "weather.svg",
76               internal: true));
77
78       ref.read(appLauncherListProvider.notifier).update(apps);
79     } catch (e) {
80       print(e);
81     }
82   }
83
84   void startApp(String id) async {
85     await appLauncher.startApplication(StartRequest(id: id));
86   }
87
88   addAppToStack(String id) {
89     if (!appStack.contains(id)) {
90       appStack.add(id);
91     } else {
92       int current = appStack.indexOf(id);
93       if (current != (appStack.length - 1)) {
94         appStack.removeAt(current);
95         appStack.add(id);
96       }
97     }
98   }
99
100   activateApp(String id) async {
101     if (appStack.last != id) {
102       var req = ActivateRequest(appId: id);
103       var response = aglShell.activateApp(req);
104       addAppToStack(id);
105     }
106   }
107
108   deactivateApp(String id) async {
109     if (appStack.contains(id)) {
110       appStack.remove(id);
111       if (appStack.isNotEmpty) {
112         activateApp(appStack.last);
113       }
114     }
115   }
116 }