Commit c2f610c4 by asranov0003

feat: add permissions page

parent dcfa5d70
import React from "react";
import React, { useEffect } from "react";
import Router from "./routes/Router";
import useTelegramExpand from "./hooks/useTelegramExpand";
import { TG_USER_ID } from "./constants/constants";
import { useAppDispatch } from "./stores/store";
import { fetchDevices } from "./stores/slices/deviceSlice";
const App: React.FC = () => {
const dispatch = useAppDispatch();
useTelegramExpand();
useEffect(() => {
if (localStorage.getItem(`token-${TG_USER_ID}`)) {
dispatch(fetchDevices());
}
}, [dispatch]);
return <Router />;
};
......
{
"common": {
"yes": "Yes",
"no": "No",
"granted": "Granted",
"denied": "Denied"
},
"auth": {
"entrance": "Sign In",
"login": "Login",
......@@ -64,6 +70,29 @@
"recoverPassword": "Recover password",
"logout": "Logout"
},
"permissions": {
"title": "Permissions",
"installedApp": "Installed apps",
"installedAppDescription": "Given access to collect data about the apps installed on the phone",
"microphone": "Microphone",
"microphoneDescription": "Allow you to record the surroundings of your child's device",
"acctivity": "Activity Recognition",
"activityDescription": "Allows you to track your child's activity",
"location": "Location",
"locationDescription": "The app will collect your child's location, even while it is closed",
"accessibility": "Accessibility",
"accessibilityDesctiption": "This permission allows you to block unwanted apps and websites, and set screeen time limits",
"systemAlert": "Draw Over Apps",
"systemAlertDescription": "This permission is necessary to control access and allow only permitted apps.",
"batteryOptimization": "Battery Optimization",
"batteryOptimizationDescription": "Battery optimization should be turn off to allow this app to work in the background",
"deviceAdmin": "Device Admin",
"deviceAdminDescription": "Admin rights are necessary to block the device and protect it from being deleted",
"notifications": "Notifications",
"notificationsDescription": "Necessary to show notifications",
"phoneState": "Phone State",
"phoneStateDescription": "This allows you to know the state of the child's phone, e.g., battery charge"
},
"pincode": {
"enterTitle": "Enter your PIN Code",
"createTitle": "Create your PIN Code",
......
{
"common": {
"yes": "Да",
"no": "Нет",
"granted": "Вкл",
"denied": "Выкл"
},
"auth": {
"entrance": "Вход",
"login": "Логин",
......@@ -64,6 +70,29 @@
"recoverPassword": "Восстановить пароль",
"logout": "Выйти"
},
"permissions": {
"title": "Разрешения",
"installedApp": "Установленные приложения",
"installedAppDescription": "Предоставляет доступ к сбору данных о приложениях, установленных на телефоне.",
"microphone": "Микрофон",
"microphoneDescription": "Позволяет записывать окружающие звуки устройства вашего ребенка.",
"activity": "Распознавание активности",
"activityDescription": "Позволяет отслеживать активность вашего ребенка.",
"location": "Местоположение",
"locationDescription": "Приложение будет собирать данные о местоположении ребенка, даже если оно закрыто.",
"accessibility": "Службы доступности",
"accessibilityDesctiption": "Это разрешение позволяет блокировать нежелательные приложения и сайты, а также устанавливать лимиты экранного времени.",
"systemAlert": "Наложение окон",
"systemAlertDescription": "Это разрешение необходимо для контроля доступа и допуска только к разрешенным приложениям.",
"batteryOptimization": "Оптимизация батареи",
"batteryOptimizationDescription": "Оптимизацию батареи следует отключить, чтобы приложение могло работать в фоновом режиме.",
"deviceAdmin": "Права администратора",
"deviceAdminDescription": "Права администратора необходимы для блокировки устройства и защиты от удаления.",
"notifications": "Уведомления",
"notificationsDescription": "Необходимо для отображения уведомлений.",
"phoneState": "Состояние телефона",
"phoneStateDescription": "Позволяет узнать состояние телефона ребенка, например уровень заряда батареи."
},
"pincode": {
"enterTitle": "Введите PIN-код",
"createTitle": "Создайте PIN-код",
......
.permissions__content {
display: flex;
flex-direction: column;
gap: 1rem;
}
.permissions__content__items {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.permissions__content__item {
display: flex;
flex-direction: column;
padding: 1rem;
background: var(--content-bg-color);
border-radius: 10px;
}
.permissions__content__item__header {
display: flex;
justify-content: space-between;
align-items: center;
}
.permissions__content__item__header div {
display: flex;
align-items: center;
gap: 0.5rem;
}
.permissions__content__item__header div p {
font-weight: bold;
}
.permission__content__item__desc {
font-size: 0.875rem;
margin-top: 0.5rem;
}
\ No newline at end of file
import React from "react";
import React, { useEffect, useState, type ReactNode } from "react";
import "./Permissions.css";
import SectionHeader from "../../layouts/SectionHeader";
import { useAppSelector, type RootState } from "../../stores/store";
import {
IoAccessibilitySharp,
IoApps,
IoBatteryHalfOutline,
IoCopyOutline,
IoPhonePortraitOutline,
IoWalkSharp,
} from "react-icons/io5";
import { FaMicrophone, FaUser } from "react-icons/fa";
import { FaLocationDot } from "react-icons/fa6";
import { IoMdNotifications } from "react-icons/io";
import { useTranslation } from "react-i18next";
interface IPermission {
id: string;
title: string;
description: string;
icon: ReactNode;
permission: string;
isGranted: boolean;
}
const Permissions: React.FC = () => {
return <div>Permissions</div>;
const [permissions, setPermissions] = useState<IPermission[]>([]);
const { selectedDevice } = useAppSelector((state: RootState) => state.device);
const { t } = useTranslation();
const permissionMeta: Record<
string,
{ title: string; description: string; icon: ReactNode }
> = {
INSTALLED_APPS: {
title: t("permissions.installedApp"),
description: t("permissions.installedAppDescription"),
icon: <IoApps className="permission__icon" />,
},
RECORD_AUDIO: {
title: t("permissions.microphone"),
description: t("permissions.microphoneDescription"),
icon: <FaMicrophone className="permission__icon" />,
},
ACTIVITY_RECOGNITION: {
title: t("permissions.activity"),
description: t("permissions.activityDescription"),
icon: <IoWalkSharp className="permission__icon" />,
},
BACKGROUND_LOCATION: {
title: t("permissions.location"),
description: t("permissions.locationDescription"),
icon: <FaLocationDot className="permission__icon" />,
},
ACCESSIBILITY_SERVICE: {
title: t("permissions.accessibility"),
description: t("permissions.accessibilityDescription"),
icon: <IoAccessibilitySharp className="permission__icon" />,
},
SYSTEM_ALERT_WINDOW: {
title: t("permissions.systemAlert"),
description: t("permissions.systemAlertDescription"),
icon: <IoCopyOutline className="permission__icon" />,
},
IGNORE_BATTERY_OPTIMIZATIONS: {
title: t("permissions.batteryOptimization"),
description: t("permissions.batteryOptimizationDescription"),
icon: <IoBatteryHalfOutline className="permission__icon" />,
},
DEVICE_ADMIN: {
title: t("permissions.deviceAdmin"),
description: t("permissions.deviceAdminDescription"),
icon: <FaUser className="permission__icon" />,
},
POST_NOTIFICATIONS: {
title: t("permissions.notifications"),
description: t("permissions.notificationsDescription"),
icon: <IoMdNotifications className="permission__icon" />,
},
READ_PHONE_STATE: {
title: t("permissions.phoneState"),
description: t("permissions.phoneStateDescription"),
icon: <IoPhonePortraitOutline className="permission__icon" />,
},
};
useEffect(() => {
if (!selectedDevice?.deviceInfo?.permissions) return;
const updatedPermissions: IPermission[] =
selectedDevice.deviceInfo.permissions.map((perm, index) => {
const meta = permissionMeta[perm.permission] || {
title: perm.permission,
description: "No description available",
icon: <i className="icon-default" />,
};
return {
id: `${index}`,
title: meta.title,
description: meta.description,
icon: meta.icon,
permission: perm.permission,
isGranted: perm.isGranted,
};
});
setPermissions(updatedPermissions);
}, [selectedDevice]);
return (
<div className="permissions wrapper">
<SectionHeader to="/home" />
<div className="permissions__content">
<h3 className="permissions__content__title">
{t("permissions.title")}
</h3>
<div className="permissions__content__items">
{permissions.map((permission) => {
return (
<div key={permission.id} className="permissions__content__item">
<div className="permissions__content__item__header">
<div>
{permission.icon}
<p>{permission.title}</p>
</div>
<div>
{permission.isGranted ? (
<p className="text-success">{t("common.granted")}</p>
) : (
<p className="text-danger">{t("common.denied")}</p>
)}
</div>
</div>
<p className="permission__content__item__desc">
{permission.description}
</p>
</div>
);
})}
</div>
</div>
</div>
);
};
export default Permissions;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment