Skip to content

Commit a4ffaa3

Browse files
committed
Merge branch 'develop'
2 parents a926f30 + 4b2f1ba commit a4ffaa3

10 files changed

Lines changed: 143 additions & 22 deletions

File tree

client/src/App.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,17 @@ function App() {
1414
const { t } = useTranslation();
1515
const [isAuthenticated, setIsAuthenticated] = useState(false);
1616
const [isLoading, setIsLoading] = useState(true);
17+
const [triggerLogout, setTriggerLogout] = useState(false);
1718

1819
useEffect(() => {
1920
checkAuthStatus();
21+
22+
// Listen for logout event from tray
23+
if (window.trayControls?.onLogout) {
24+
window.trayControls.onLogout(() => {
25+
setTriggerLogout(true);
26+
});
27+
}
2028
}, []);
2129

2230
const checkAuthStatus = async () => {
@@ -79,7 +87,7 @@ function App() {
7987
path="/"
8088
element={
8189
isAuthenticated ? (
82-
<Dashboard onLogout={handleLogout} />
90+
<Dashboard onLogout={handleLogout} triggerLogout={triggerLogout} setTriggerLogout={setTriggerLogout} />
8391
) : (
8492
<Navigate to="/login" replace />
8593
)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
4+
interface ConfirmLogoutModalProps {
5+
isOpen: boolean;
6+
onConfirm: () => void;
7+
onCancel: () => void;
8+
}
9+
10+
function ConfirmLogoutModal({ isOpen, onConfirm, onCancel }: ConfirmLogoutModalProps) {
11+
const { t } = useTranslation();
12+
13+
if (!isOpen) return null;
14+
15+
return (
16+
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50">
17+
<div className="bg-gray-900 rounded-lg p-6 max-w-md w-full mx-4 border border-gray-700">
18+
<h2 className="text-xl font-semibold text-white mb-4">
19+
{t('logout.confirmTitle')}
20+
</h2>
21+
<p className="text-gray-300 mb-6">
22+
{t('logout.confirmMessage')}
23+
</p>
24+
<div className="flex justify-end space-x-3">
25+
<button
26+
onClick={onCancel}
27+
className="px-4 py-2 bg-gray-700 hover:bg-gray-600 text-white rounded-md transition-colors"
28+
>
29+
{t('logout.cancelButton')}
30+
</button>
31+
<button
32+
onClick={onConfirm}
33+
className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-md transition-colors"
34+
>
35+
{t('logout.confirmButton')}
36+
</button>
37+
</div>
38+
</div>
39+
</div>
40+
);
41+
}
42+
43+
export default ConfirmLogoutModal;

client/src/components/Dashboard.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import {BookShelfEntity, BookShelfResponse} from "../interfaces/books";
1010

1111
interface DashboardProps {
1212
onLogout: () => void;
13+
triggerLogout?: boolean;
14+
setTriggerLogout?: (value: boolean) => void;
1315
}
1416

15-
function Dashboard({onLogout}: DashboardProps) {
17+
function Dashboard({onLogout, triggerLogout, setTriggerLogout}: DashboardProps) {
1618
const { t } = useTranslation();
1719
const navigate = useNavigate();
1820
const [books, setBooks] = useState<BookShelfEntity[]>([]);
@@ -71,7 +73,11 @@ function Dashboard({onLogout}: DashboardProps) {
7173

7274
return (
7375
<div className="min-h-screen bg-black text-white">
74-
<DashboardHeader onLogout={onLogout}/>
76+
<DashboardHeader
77+
onLogout={onLogout}
78+
triggerLogout={triggerLogout}
79+
setTriggerLogout={setTriggerLogout}
80+
/>
7581

7682
{/* Main Content */}
7783
<main className="max-w-4xl mx-auto py-6 px-4 pb-32">

client/src/components/DashboardHeader.tsx

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,64 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import ConfirmLogoutModal from './ConfirmLogoutModal';
4+
5+
interface DashboardHeaderProps {
6+
onLogout: () => void;
7+
triggerLogout?: boolean;
8+
setTriggerLogout?: (value: boolean) => void;
9+
}
10+
11+
function DashboardHeader({ onLogout, triggerLogout, setTriggerLogout }: DashboardHeaderProps) {
12+
const { t } = useTranslation();
13+
const [showConfirmModal, setShowConfirmModal] = useState(false);
14+
15+
useEffect(() => {
16+
if (triggerLogout) {
17+
setShowConfirmModal(true);
18+
if (setTriggerLogout) {
19+
setTriggerLogout(false);
20+
}
21+
}
22+
}, [triggerLogout, setTriggerLogout]);
23+
24+
const handleLogoutClick = () => {
25+
setShowConfirmModal(true);
26+
};
27+
28+
const handleConfirmLogout = () => {
29+
setShowConfirmModal(false);
30+
onLogout();
31+
};
32+
33+
const handleCancelLogout = () => {
34+
setShowConfirmModal(false);
35+
};
236

3-
// TODO: Define proper interface for DashboardHeader props
4-
function DashboardHeader({ onLogout }: { onLogout: any }) {
537
return (
6-
<nav className="bg-black border-b border-gray-800">
7-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
8-
<div className="flex justify-between h-16">
9-
<div className="flex items-center">
10-
<img src={'assets/icon.png'} alt={"Storytel"} className="w-12 h-12"/>
11-
</div>
12-
<div className="flex items-center space-x-4">
13-
<button
14-
onClick={onLogout}
15-
className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-md text-sm font-medium transition-colors"
16-
>
17-
Logout
18-
</button>
38+
<>
39+
<nav className="bg-black border-b border-gray-800">
40+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
41+
<div className="flex justify-between h-16">
42+
<div className="flex items-center">
43+
<img src={'assets/icon.png'} alt={"Storytel"} className="w-12 h-12"/>
44+
</div>
45+
<div className="flex items-center space-x-4">
46+
<button
47+
onClick={handleLogoutClick}
48+
className="bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-md text-sm font-medium transition-colors"
49+
>
50+
{t('dashboard.logout')}
51+
</button>
52+
</div>
1953
</div>
2054
</div>
21-
</div>
22-
</nav>
55+
</nav>
56+
<ConfirmLogoutModal
57+
isOpen={showConfirmModal}
58+
onConfirm={handleConfirmLogout}
59+
onCancel={handleCancelLogout}
60+
/>
61+
</>
2362
);
2463
}
2564

client/src/types/window.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ declare global {
1313
off?: (event: string) => void;
1414
onPlayPause?: (callback: () => void) => void;
1515
onSetSpeed?: (callback: (event: any, speed: number) => void) => void;
16+
onLogout?: (callback: () => void) => void;
1617
};
1718
electronLocale?: {
1819
getLocale: () => Promise<string>;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "storytel-player",
3-
"version": "1.0.6",
3+
"version": "1.0.7",
44
"email": "andrea@debbaweb.it",
55
"description": "Storytel Unofficial Player - Storytel audiobook player for desktop",
66
"main": "dist/electron/main.js",

server/locales/en.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@
100100
"showApp": "Show App",
101101
"playPause": "Play/Pause",
102102
"playbackSpeed": "Playback Speed",
103+
"logout": "Logout",
103104
"quit": "Quit"
105+
},
106+
"logout": {
107+
"confirmTitle": "Confirm Logout",
108+
"confirmMessage": "Are you sure you want to logout?",
109+
"confirmButton": "Logout",
110+
"cancelButton": "Cancel"
104111
}
105112
}

server/locales/it.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@
100100
"showApp": "Mostra App",
101101
"playPause": "Play/Pausa",
102102
"playbackSpeed": "Velocità di Riproduzione",
103+
"logout": "Logout",
103104
"quit": "Esci"
105+
},
106+
"logout": {
107+
"confirmTitle": "Conferma Logout",
108+
"confirmMessage": "Sei sicuro di voler effettuare il logout?",
109+
"confirmButton": "Logout",
110+
"cancelButton": "Annulla"
104111
}
105112
}

src/modules/tray.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ export class TrayManager {
8080

8181
menuTemplate.push(
8282
{type: 'separator'},
83+
{
84+
label: i18n.t('tray.logout'),
85+
click: () => {
86+
this.windowManager.show();
87+
this.sendToRenderer('tray-logout');
88+
},
89+
},
8390
{
8491
label: i18n.t('tray.quit'),
8592
click: () => {

src/preload.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ contextBridge.exposeInMainWorld('trayControls', {
2121
onSetSpeed: (callback: (_event: IpcRendererEvent, speed: number) => void): void => {
2222
ipcRenderer.on('tray-set-speed', callback);
2323
},
24+
onLogout: (callback: () => void): void => {
25+
ipcRenderer.on('tray-logout', callback);
26+
},
2427
updatePlayingState: (isPlaying: boolean, bookTitle: string): void => {
2528
ipcRenderer.send('update-playing-state', { isPlaying, bookTitle });
2629
},

0 commit comments

Comments
 (0)