Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
thecybernanny-webapp
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
asranov0003
thecybernanny-webapp
Commits
f6dd96ab
Commit
f6dd96ab
authored
Jul 16, 2025
by
asranov0003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: render black and white lists
parent
b840a4ff
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
156 additions
and
15 deletions
+156
-15
BlockApps.tsx
src/pages/BlockApps/BlockApps.tsx
+57
-15
appsSlice.ts
src/stores/slices/appsSlice.ts
+99
-0
No files found.
src/pages/BlockApps/BlockApps.tsx
View file @
f6dd96ab
import
React
,
{
useEffect
,
useState
}
from
"react"
;
import
React
,
{
use
Callback
,
use
Effect
,
useState
}
from
"react"
;
import
"./BlockApps.css"
;
import
SectionHeader
from
"../../layouts/SectionHeader"
;
import
{
LuWalletCards
}
from
"react-icons/lu"
;
...
...
@@ -10,7 +10,11 @@ import {
useAppSelector
,
type
RootState
,
}
from
"../../stores/store"
;
import
{
fetchAppList
}
from
"../../stores/slices/appsSlice"
;
import
{
fetchAppList
,
fetchBlackList
,
fetchWhiteList
,
}
from
"../../stores/slices/appsSlice"
;
const
BlockApps
:
React
.
FC
=
()
=>
{
const
[
selectedTab
,
setSelectedTab
]
=
useState
<
"all"
|
"blocked"
|
"allowed"
>
(
...
...
@@ -18,12 +22,22 @@ const BlockApps: React.FC = () => {
);
const
{
t
}
=
useTranslation
();
const
{
selectedDevice
}
=
useAppSelector
((
state
:
RootState
)
=>
state
.
device
);
const
{
allApps
}
=
useAppSelector
((
state
:
RootState
)
=>
state
.
apps
);
const
{
allApps
,
blackList
,
whiteList
}
=
useAppSelector
(
(
state
:
RootState
)
=>
state
.
apps
);
const
dispatch
=
useAppDispatch
();
const
fetchDatas
=
useCallback
(
async
()
=>
{
const
deviceId
=
selectedDevice
?.
id
||
""
;
await
dispatch
(
fetchAppList
(
deviceId
));
await
dispatch
(
fetchBlackList
(
deviceId
));
await
dispatch
(
fetchWhiteList
(
deviceId
));
},
[
selectedDevice
?.
id
,
dispatch
]);
useEffect
(()
=>
{
dispatch
(
fetchAppList
(
selectedDevice
?.
id
||
""
)
);
},
[
selectedDevice
,
dispatch
]);
fetchDatas
(
);
},
[
fetchDatas
]);
const
renderTabContent
=
()
=>
{
switch
(
selectedTab
)
{
...
...
@@ -67,36 +81,64 @@ const BlockApps: React.FC = () => {
return
(
<
div
className=
"blockapps__content"
>
<
h3
className=
"blockapps__content__title"
>
{
t
(
"blockapps.blockedApps"
)
}
(
0
)
{
t
(
"blockapps.blockedApps"
)
}
(
{
blackList
.
length
}
)
</
h3
>
<
div
className=
"blockapps__content__actions"
>
<
CButton
title=
{
t
(
"blockapps.unBlock"
)
}
disabled
/>
</
div
>
<
div
className=
"blockapps__content__empty"
>
<
p
>
{
t
(
"blockapps.noFoundApps"
)
}
</
p
>
</
div
>
{
blackList
.
length
===
0
&&
(
<
div
className=
"blockapps__content__empty"
>
<
p
>
{
t
(
"blockapps.noFoundApps"
)
}
</
p
>
</
div
>
)
}
<
div
className=
"blockapps__content__apps"
></
div
>
<
div
className=
"blockapps__content__apps"
>
{
blackList
.
map
((
app
,
index
)
=>
{
return
(
<
div
key=
{
index
}
className=
"blockapps__content__app"
>
<
img
src=
{
`data:image/jpeg;base64,${app.appIcon}`
}
alt=
{
app
.
appName
}
/>
<
h4
>
{
app
.
appName
}
</
h4
>
</
div
>
);
})
}
</
div
>
</
div
>
);
case
"allowed"
:
return
(
<
div
className=
"blockapps__content"
>
<
h3
className=
"blockapps__content__title"
>
{
t
(
"blockapps.allowedApps"
)
}
(
0
)
{
t
(
"blockapps.allowedApps"
)
}
(
{
whiteList
.
length
}
)
</
h3
>
<
div
className=
"blockapps__content__actions"
>
<
CButton
title=
{
t
(
"blockapps.remove"
)
}
disabled
/>
</
div
>
<
div
className=
"blockapps__content__empty"
>
<
p
>
{
t
(
"blockapps.noFoundApps"
)
}
</
p
>
</
div
>
{
whiteList
.
length
===
0
&&
(
<
div
className=
"blockapps__content__empty"
>
<
p
>
{
t
(
"blockapps.noFoundApps"
)
}
</
p
>
</
div
>
)
}
<
div
className=
"blockapps__content__apps"
></
div
>
<
div
className=
"blockapps__content__apps"
>
{
whiteList
.
map
((
app
,
index
)
=>
{
return
(
<
div
key=
{
index
}
className=
"blockapps__content__app"
>
<
img
src=
{
`data:image/jpeg;base64,${app.appIcon}`
}
alt=
{
app
.
appName
}
/>
<
h4
>
{
app
.
appName
}
</
h4
>
</
div
>
);
})
}
</
div
>
</
div
>
);
default
:
...
...
src/stores/slices/appsSlice.ts
View file @
f6dd96ab
...
...
@@ -11,12 +11,20 @@ export interface IApp {
interface
AppsState
{
allApps
:
IApp
[];
blackList
:
IApp
[];
whiteList
:
IApp
[];
isLoadingAllApps
:
boolean
;
isLoadingBlackList
:
boolean
;
isLoadingWhiteList
:
boolean
;
}
const
initialState
:
AppsState
=
{
allApps
:
[],
blackList
:
[],
whiteList
:
[],
isLoadingAllApps
:
false
,
isLoadingBlackList
:
false
,
isLoadingWhiteList
:
false
,
};
export
const
fetchAppList
=
createAsyncThunk
(
...
...
@@ -28,6 +36,8 @@ export const fetchAppList = createAsyncThunk(
wIcons
:
true
,
});
console
.
log
(
"All Apps Response: "
,
response
.
list
);
return
response
.
list
;
}
catch
(
error
)
{
if
(
typeof
error
===
"object"
&&
error
!==
null
&&
"message"
in
error
)
{
...
...
@@ -39,6 +49,70 @@ export const fetchAppList = createAsyncThunk(
}
);
export
const
fetchBlackList
=
createAsyncThunk
(
"apps/fetchBlackList"
,
async
(
deviceId
:
string
,
{
rejectWithValue
,
getState
})
=>
{
try
{
const
response
=
await
sendRpcRequest
<
{
list
:
string
[]
}
>
(
"apps.blacklist"
,
{
deviceId
,
}
);
const
state
=
getState
()
as
{
apps
:
AppsState
};
const
allApps
=
state
.
apps
.
allApps
;
const
filtered
=
allApps
.
filter
((
app
)
=>
response
.
list
.
includes
(
app
.
pkgName
)
);
return
filtered
;
}
catch
(
error
)
{
if
(
typeof
error
===
"object"
&&
error
!==
null
&&
"message"
in
error
)
{
return
rejectWithValue
(
error
.
message
);
}
return
rejectWithValue
(
"Unknown error occurred"
);
}
}
);
export
const
fetchWhiteList
=
createAsyncThunk
(
"apps/fetchWhiteList"
,
async
(
deviceId
:
string
,
{
rejectWithValue
,
getState
,
dispatch
})
=>
{
const
state
=
getState
()
as
{
apps
:
AppsState
};
if
(
state
.
apps
.
allApps
.
length
===
0
)
{
const
result
=
await
dispatch
(
fetchAppList
(
deviceId
));
if
(
fetchAppList
.
rejected
.
match
(
result
))
{
return
rejectWithValue
(
"Failed to fetch all apps before whitelist."
);
}
}
try
{
const
response
=
await
sendRpcRequest
<
{
list
:
string
[]
}
>
(
"apps.whitelist"
,
{
deviceId
}
);
const
updatedState
=
getState
()
as
{
apps
:
AppsState
};
const
allApps
=
updatedState
.
apps
.
allApps
;
const
filtered
=
allApps
.
filter
((
app
)
=>
response
.
list
.
includes
(
app
.
pkgName
)
);
return
filtered
;
}
catch
(
error
)
{
if
(
typeof
error
===
"object"
&&
error
!==
null
&&
"message"
in
error
)
{
return
rejectWithValue
(
error
.
message
);
}
return
rejectWithValue
(
"Unknown error occurred"
);
}
}
);
const
appsSlice
=
createSlice
({
name
:
"apps"
,
initialState
,
...
...
@@ -51,6 +125,31 @@ const appsSlice = createSlice({
.
addCase
(
fetchAppList
.
fulfilled
,
(
state
,
action
)
=>
{
state
.
isLoadingAllApps
=
false
;
state
.
allApps
=
action
.
payload
;
})
.
addCase
(
fetchAppList
.
rejected
,
(
state
)
=>
{
state
.
isLoadingAllApps
=
false
;
})
.
addCase
(
fetchBlackList
.
pending
,
(
state
)
=>
{
state
.
isLoadingBlackList
=
true
;
})
.
addCase
(
fetchBlackList
.
fulfilled
,
(
state
,
action
)
=>
{
state
.
isLoadingBlackList
=
false
;
state
.
blackList
=
action
.
payload
;
})
.
addCase
(
fetchBlackList
.
rejected
,
(
state
)
=>
{
state
.
isLoadingBlackList
=
false
;
})
.
addCase
(
fetchWhiteList
.
pending
,
(
state
)
=>
{
state
.
isLoadingWhiteList
=
true
;
})
.
addCase
(
fetchWhiteList
.
fulfilled
,
(
state
,
action
)
=>
{
state
.
isLoadingWhiteList
=
false
;
state
.
whiteList
=
action
.
payload
;
})
.
addCase
(
fetchWhiteList
.
rejected
,
(
state
)
=>
{
state
.
isLoadingWhiteList
=
false
;
});
},
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment