Skip to content
This repository has been archived by the owner on Jan 1, 2025. It is now read-only.

Commit

Permalink
feat: adding account profile info
Browse files Browse the repository at this point in the history
  • Loading branch information
RossComputerGuy committed May 2, 2024
1 parent 8fb56c8 commit fffe8e3
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 10 deletions.
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

src = lib.cleanSource self;

buildInputs = with s; [ pam ];
buildInputs = with s; [ pam accountsservice polkit ];

pubspecLock = lib.importJSON ./pubspec.lock.json;

Expand Down
64 changes: 64 additions & 0 deletions lib/widgets/account_profile.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class AccountProfile extends StatefulWidget {
const AccountProfile({ super.key }) : uid = null, name = null;
const AccountProfile.uid({ super.key, required this.uid }) : name = null;
const AccountProfile.name({ super.key, required this.name }) : uid = null;

final int? uid;
final String? name;

@override
State<AccountProfile> createState() => _AccountProfileState();
}

class _AccountProfileState extends State<AccountProfile> {
static const platform = MethodChannel('com.expidusos.genesis.shell/account');

String? displayName = null;
String? icon = null;

dynamic _getData() {
if (widget.uid != null) return widget.uid;
if (widget.name != null) return widget.name;
return null;
}

@override
void initState() {
super.initState();

platform.invokeMethod('get', _getData()).then((user) => setState(() {
displayName = user['displayName'];
icon = user['icon'];
print(user);
})).catchError((err) {
print(err);
});
}

Widget build(BuildContext context) =>
Row(
children: [
icon == null
? Icon(Icons.account_circle, size: 40)
: ClipRRect(
borderRadius: BorderRadius.circular(360.0),
child: Image.file(
File(icon!),
width: 40,
height: 40,
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: Text(
displayName ?? '',
style: Theme.of(context).textTheme.titleLarge,
),
),
],
);
}
4 changes: 4 additions & 0 deletions lib/widgets/system_drawer.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';

import '../logic/power.dart';

import 'account_profile.dart';
import 'power.dart';

class SystemDrawer extends StatelessWidget {
Expand All @@ -17,7 +19,9 @@ class SystemDrawer extends StatelessWidget {
Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
shrinkWrap: true,
children: [
userMode && !Breakpoints.small.isActive(context) ? const AccountProfile() : null,
userMode ? Row(
children: [
Expanded(
Expand Down
26 changes: 24 additions & 2 deletions lib/widgets/system_layout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:backdrop/backdrop.dart';
import 'package:flutter/material.dart';
import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart';

import 'account_profile.dart';
import 'output_layout.dart';
import 'system_bar.dart';
import 'system_drawer.dart';
Expand Down Expand Up @@ -42,8 +43,29 @@ class SystemLayout extends StatelessWidget {
backgroundColor: Theme.of(context).colorScheme.background,
),
),
child: SystemDrawer(
userMode: userMode,
child: Column(
children: [
userMode && Breakpoints.small.isActive(context)
? Row(
children: [
Expanded(
child: Container(
decoration: ShapeDecoration(
shape: const LinearBorder(),
color: Theme.of(context).colorScheme.background,
),
child: const Padding(
padding: const EdgeInsets.all(8),
child: AccountProfile(),
),
),
),
],
) : null,
SystemDrawer(
userMode: userMode,
),
].where((e) => e != null).toList().cast<Widget>(),
),
),
),
Expand Down
4 changes: 3 additions & 1 deletion linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR})

# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(ACCOUNTSSERVICE REQUIRED IMPORTED_TARGET accountsservice)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(PAM REQUIRED IMPORTED_TARGET pam)

Expand All @@ -64,6 +65,7 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
add_executable(${BINARY_NAME}
"main.cc"
"application.cc"
"channels/account.cc"
"channels/auth.cc"
"channels/outputs.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
Expand All @@ -75,7 +77,7 @@ apply_standard_settings(${BINARY_NAME})

# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK PkgConfig::PAM)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::ACCOUNTSSERVICE PkgConfig::GTK PkgConfig::PAM)

# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)
Expand Down
1 change: 1 addition & 0 deletions linux/application-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ struct _GenesisShellApplication {
GtkApplication parent_instance;
char** dart_entrypoint_arguments;
FlMethodChannel* outputs;
FlMethodChannel* account;
FlMethodChannel* auth;
GtkWindow* win;
};
7 changes: 7 additions & 0 deletions linux/application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "application.h"
#include "application-priv.h"
#include "channels/auth.h"
#include "channels/account.h"
#include "channels/outputs.h"

#include <flutter_linux/flutter_linux.h>
Expand Down Expand Up @@ -39,6 +40,12 @@ static void genesis_shell_application_activate(GApplication* application) {
fl_method_channel_set_method_call_handler(self->outputs, outputs_method_call_handler, self, nullptr);
}

{
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
self->account = fl_method_channel_new(fl_engine_get_binary_messenger(fl_view_get_engine(view)), "com.expidusos.genesis.shell/account", FL_METHOD_CODEC(codec));
fl_method_channel_set_method_call_handler(self->account, account_method_call_handler, self, nullptr);
}

{
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
self->auth = fl_method_channel_new(fl_engine_get_binary_messenger(fl_view_get_engine(view)), "com.expidusos.genesis.shell/auth", FL_METHOD_CODEC(codec));
Expand Down
71 changes: 71 additions & 0 deletions linux/channels/account.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <flutter_linux/flutter_linux.h>

extern "C" {
#include <act/act.h>
}

#include <sys/types.h>
#include <unistd.h>

#include "account.h"
#include "../application-priv.h"

static FlValue* new_string(const gchar* str) {
if (str == nullptr) return fl_value_new_null();
return fl_value_new_string(str);
}

static FlValue* from_user(ActUser* usr) {
if (usr == nullptr) return fl_value_new_null();

FlValue* value = fl_value_new_map();
fl_value_set(value, fl_value_new_string("name"), new_string(act_user_get_user_name(usr)));
fl_value_set(value, fl_value_new_string("displayName"), new_string(act_user_get_real_name(usr)));
fl_value_set(value, fl_value_new_string("icon"), new_string(act_user_get_icon_file(usr)));
return value;
}

void account_method_call_handler(FlMethodChannel* channel, FlMethodCall* method_call, gpointer user_data) {
g_autoptr(FlMethodResponse) response = nullptr;

ActUserManager* mngr = act_user_manager_get_default();
if (act_user_manager_no_service(mngr)) {
fl_method_call_respond_error(method_call, "AccountsService", "Service has not started.", nullptr, nullptr);
return;
}

if (strcmp(fl_method_call_get_name(method_call), "get") == 0) {
FlValue* args = fl_method_call_get_args(method_call);
switch (fl_value_get_type(args)) {
case FL_VALUE_TYPE_NULL:
response = FL_METHOD_RESPONSE(fl_method_success_response_new(from_user(act_user_manager_get_user_by_id(mngr, geteuid()))));
break;
case FL_VALUE_TYPE_INT:
response = FL_METHOD_RESPONSE(fl_method_success_response_new(from_user(act_user_manager_get_user_by_id(mngr, fl_value_get_int(args)))));
break;
case FL_VALUE_TYPE_STRING:
response = FL_METHOD_RESPONSE(fl_method_success_response_new(from_user(act_user_manager_get_user(mngr, fl_value_get_string(args)))));
break;
default:
fl_method_call_respond_error(method_call, "AccountsService", "Unknown type", args, nullptr);
return;
}
} else if (strcmp(fl_method_call_get_name(method_call), "list") == 0) {
g_autoptr(FlValue) value = fl_value_new_list();

GSList* list = act_user_manager_list_users(mngr);
while (list != nullptr) {
fl_value_append(value, from_user(ACT_USER(list->data)));
list = list->next;
}

response = FL_METHOD_RESPONSE(fl_method_success_response_new(value));
} else {
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
}

g_autoptr(GError) error = nullptr;
if (!fl_method_call_respond(method_call, response, &error)) {
g_warning("Failed to send response: %s", error->message);
}
}
7 changes: 7 additions & 0 deletions linux/channels/account.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <flutter_linux/flutter_linux.h>

#include "../application.h"

void account_method_call_handler(FlMethodChannel* channel, FlMethodCall* method_call, gpointer user_data);

0 comments on commit fffe8e3

Please sign in to comment.