- {DesktopAppsList.map((iconConfig) => {
+ {apps.filter(iconConfig => !iconConfig.indock).map((iconConfig) => {
// Convert the icon's priority into an (x,y) position,
// now using GRID_GAP to keep them spaced out.
const position = getPositionFromPriority(iconConfig.priority);
@@ -49,7 +47,7 @@ function Desktop({ onOpenApp }) {
isSelected={selectedIcon === iconConfig.id}
onClick={() => handleIconClick(iconConfig.id)}
onDoubleClick={() => onOpenApp(iconConfig.id)}
- position={position}
+ position={position}
/>
);
})}
diff --git a/src/components/MiniApps/MiniApps.jsx b/src/components/MiniApps/MiniApps.jsx
index e2a38d0b..a33ea9cd 100644
--- a/src/components/MiniApps/MiniApps.jsx
+++ b/src/components/MiniApps/MiniApps.jsx
@@ -69,7 +69,6 @@ function MiniApps() {
.filter(app => app.available)
.filter(app => {
if (app.id === 'battery' && deviceInfo.battery.level === null) return false;
- if (app.id === 'user' && deviceInfo.orientation === 'portrait') return false;
return true;
})
.slice()
diff --git a/src/lists/DesktopAppsList.jsx b/src/lists/DesktopAppsList.jsx
index 33450c4d..8bd47b48 100644
--- a/src/lists/DesktopAppsList.jsx
+++ b/src/lists/DesktopAppsList.jsx
@@ -8,6 +8,8 @@ import awaiIcon from '../media/icons/awai.png';
/**
* Each icon now has a `priority` which determines its order on the desktop grid.
* Additionally, apps that are only links have a `link` property.
+ * The new `indock` field determines if the icon should be displayed on the desktop.
+ * If `indock` is true, the icon will not be rendered on the desktop.
*/
const DesktopAppsList = [
{
@@ -16,6 +18,7 @@ const DesktopAppsList = [
icon: defaultIcon,
component: SortingAlgorithms,
priority: 4,
+ indock: false,
},
{
@@ -24,6 +27,7 @@ const DesktopAppsList = [
icon: folderIcon,
component: null,
priority: 5,
+ indock: true, // This icon will not display on the desktop
},
{
@@ -33,6 +37,7 @@ const DesktopAppsList = [
link: 'http://linkedin.com/in/htdguide/',
component: null,
priority: 2,
+ indock: false,
},
{
@@ -42,6 +47,7 @@ const DesktopAppsList = [
link: 'https://github.com/htdguide',
component: null,
priority: 1,
+ indock: true, // This icon will not display on the desktop
},
{
@@ -51,6 +57,7 @@ const DesktopAppsList = [
link: 'https://applywithai.com',
component: null,
priority: 3,
+ indock: false,
},
// Add more apps here as needed, with increasing `priority`
diff --git a/src/miniapps/ControlCentreMiniApp/ControlCentreMiniApp.css b/src/miniapps/ControlCentreMiniApp/ControlCentreMiniApp.css
index 7e722078..821c16fa 100644
--- a/src/miniapps/ControlCentreMiniApp/ControlCentreMiniApp.css
+++ b/src/miniapps/ControlCentreMiniApp/ControlCentreMiniApp.css
@@ -7,7 +7,15 @@
width: 280px;
/* Semi-translucent white with blur, to mimic macOS style */
background: rgba(255, 255, 255, 0.5);
+
+ /* Ensures the blur effect works in Safari */
+ -webkit-backdrop-filter: blur(16px);
backdrop-filter: blur(16px);
+
+ /* Prevents artefacts in Safari */
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+
margin-top: 6px;
padding-left: 10px;
padding-right: 10px;
@@ -23,7 +31,12 @@
/* Each “segment” or “card” in the control center */
.cc-segment {
- backdrop-filter: blur(1px);
+ background: rgba(255, 255, 255, 0.5);
+
+ /* Clip the background to avoid artefacts */
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+
border-radius: 12px;
padding: 12px 16px;
margin-top: 10px;
diff --git a/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.css b/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.css
index 54c55dfd..eba97ae8 100644
--- a/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.css
+++ b/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.css
@@ -30,7 +30,7 @@
.song-title-container {
overflow: hidden;
white-space: nowrap;
- margin-top: -7px;
+ margin-top: -5px;
margin-left: 2px;
}
diff --git a/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.jsx b/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.jsx
index 5b69af57..7a11bbc7 100644
--- a/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.jsx
+++ b/src/miniapps/ControlCentreMiniApp/ControlCentreWidgets/MusicControl/MusicControl.jsx
@@ -36,11 +36,12 @@ function MusicControl() {
#888 80%)`
};
- // Convert seconds to mm:ss
+ // Convert seconds to mm:ss, cutting off milliseconds
const formatTime = (secs) => {
if (!secs || secs < 0) secs = 0;
- const minutes = Math.floor(secs / 60);
- const seconds = secs % 60;
+ const totalSeconds = Math.floor(secs); // <-- Truncate decimal part
+ const minutes = Math.floor(totalSeconds / 60);
+ const seconds = totalSeconds % 60;
return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
};
diff --git a/src/services/AppsContext/AppsContext.jsx b/src/services/AppsContext/AppsContext.jsx
new file mode 100644
index 00000000..f0f21348
--- /dev/null
+++ b/src/services/AppsContext/AppsContext.jsx
@@ -0,0 +1,73 @@
+import React, { createContext, useState } from 'react';
+import defaultIcon from '../../media/icons/defaultapp.png'; // Example icon
+import folderIcon from '../../media/icons/folder.webp';
+import SortingAlgorithms from '../../apps/SortingAlgorithms/SortingAlgorithms.jsx';
+import linkedinIcon from '../../media/icons/linkedin.png';
+import githubIcon from '../../media/icons/github.png';
+import awaiIcon from '../../media/icons/awai.png';
+
+/**
+ * The initial list of apps.
+ * The `indock` field determines if the icon should be rendered on the desktop.
+ * If `indock` is true, the icon will not be rendered on the desktop.
+ */
+const initialAppsList = [
+ {
+ id: 'sorting-algorithms',
+ name: 'Sorting Algorithms',
+ icon: defaultIcon,
+ component: SortingAlgorithms,
+ priority: 4,
+ indock: false,
+ },
+ {
+ id: 'untitled-folder',
+ name: 'untitled folder',
+ icon: folderIcon,
+ component: null,
+ priority: 5,
+ indock: true, // Initially in the dock, so not on desktop
+ },
+ {
+ id: 'linkedin',
+ name: 'LinkedIn',
+ icon: linkedinIcon,
+ link: 'http://linkedin.com/in/htdguide/',
+ component: null,
+ priority: 2,
+ indock: false,
+ },
+ {
+ id: 'github',
+ name: 'Github',
+ icon: githubIcon,
+ link: 'https://github.com/htdguide',
+ component: null,
+ priority: 1,
+ indock: false, // Initially in the dock, so not on desktop
+ },
+ {
+ id: 'awai',
+ name: 'ApplyWithAI',
+ icon: awaiIcon,
+ link: 'https://applywithai.com',
+ component: null,
+ priority: 3,
+ indock: false,
+ },
+];
+
+export const AppsContext = createContext({
+ apps: initialAppsList,
+ setApps: () => {},
+});
+
+export const AppsProvider = ({ children }) => {
+ const [apps, setApps] = useState(initialAppsList);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/src/services/MusicService/MusicService.jsx b/src/services/MusicService/MusicService.jsx
index 8625df15..5c0b4795 100644
--- a/src/services/MusicService/MusicService.jsx
+++ b/src/services/MusicService/MusicService.jsx
@@ -1,283 +1,430 @@
// MusicService.jsx
import React, {
- createContext,
- useContext,
- useRef,
- useState,
- useEffect,
- useCallback,
- } from 'react';
-
- // Import jsmediatags from the UMD build to avoid Vite dep-scan issues
- import jsmediatags from 'jsmediatags/dist/jsmediatags.min.js';
-
- // Import our config
- import musicServiceConfig from '../../configs/MusicServiceConfig/MusicServiceConfig';
-
- // Create the context
- const MusicServiceContext = createContext(null);
-
- // Custom hook
- export function useMusicService() {
- return useContext(MusicServiceContext);
- }
-
- export function MusicServiceProvider({ children }) {
- // We'll store the loaded list of MP3 "entries" from the JSON.
- const [musicList, setMusicList] = useState([]);
-
- // The