nekostream 2026.2.1 → 2026.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nekostream",
3
- "version": "2026.2.1",
3
+ "version": "2026.2.2",
4
4
  "description": "Bettter version of NekoStream ",
5
5
  "keywords": [
6
6
  "anime",
package/player-main.js CHANGED
@@ -4,13 +4,28 @@ const path = require('path')
4
4
 
5
5
  let mainWindow = null
6
6
 
7
- function logToRenderer(msg) {
8
- if (mainWindow && !mainWindow.isDestroyed() && mainWindow.webContents) {
9
- mainWindow.webContents.send('main-log', msg);
10
- }
11
- }
12
-
13
- function createWindow() {
7
+ function logToRenderer(msg) {
8
+ if (mainWindow && !mainWindow.isDestroyed() && mainWindow.webContents) {
9
+ mainWindow.webContents.send('main-log', msg);
10
+ }
11
+ }
12
+
13
+ ipcMain.on('player:minimize', () => {
14
+ if (mainWindow && !mainWindow.isDestroyed()) {
15
+ mainWindow.minimize()
16
+ }
17
+ })
18
+
19
+ ipcMain.on('player:toggle-maximize', () => {
20
+ if (!mainWindow || mainWindow.isDestroyed()) return
21
+ if (mainWindow.isMaximized()) {
22
+ mainWindow.unmaximize()
23
+ } else {
24
+ mainWindow.maximize()
25
+ }
26
+ })
27
+
28
+ function createWindow() {
14
29
  const streamData = process.env.NEKOSTREAM_CLI_STREAM
15
30
  if (!streamData) {
16
31
  console.error('No stream data provided.')
package/player.html CHANGED
@@ -14,48 +14,82 @@
14
14
  overflow: hidden;
15
15
  font-family: sans-serif;
16
16
  }
17
- #player-container {
18
- width: 100%;
19
- height: 100%;
20
- }
17
+ #player-container {
18
+ width: 100%;
19
+ height: 100%;
20
+ }
21
21
  webview {
22
22
  width: 100%;
23
23
  height: 100%;
24
24
  border: none;
25
25
  }
26
- #close-btn, .dev-btn {
27
- position: absolute;
28
- top: 20px;
29
- z-index: 9999;
30
- background: rgba(0, 0, 0, 0.5);
31
- color: white;
32
- border: 1px solid rgba(255, 255, 255, 0.2);
33
- padding: 8px 16px;
34
- cursor: pointer;
35
- border-radius: 4px;
36
- font-size: 14px;
37
- transition: background 0.2s;
38
- -webkit-app-region: no-drag;
39
- }
40
- #close-btn {
41
- right: 20px;
42
- }
43
- #close-btn:hover {
44
- background: rgba(255, 0, 0, 0.7);
45
- }
46
- .dev-btn:hover {
47
- background: rgba(37, 99, 235, 0.7);
48
- }
49
- .drag-region {
50
- position: absolute;
51
- top: 0;
52
- left: 0;
53
- right: 80px;
54
- height: 40px;
55
- -webkit-app-region: drag;
56
- z-index: 9998;
57
- }
58
- #loading-overlay {
26
+ #top-nav {
27
+ position: absolute;
28
+ top: 0;
29
+ left: 0;
30
+ right: 0;
31
+ height: 44px;
32
+ z-index: 10000;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: space-between;
36
+ background: linear-gradient(to bottom, rgba(5, 8, 13, 0.82), rgba(5, 8, 13, 0.22), rgba(5, 8, 13, 0));
37
+ color: rgba(255, 255, 255, 0.92);
38
+ -webkit-app-region: drag;
39
+ user-select: none;
40
+ pointer-events: auto;
41
+ }
42
+ .nav-title {
43
+ min-width: 0;
44
+ padding-left: 16px;
45
+ font-size: 13px;
46
+ font-weight: 600;
47
+ letter-spacing: 0.01em;
48
+ color: rgba(255, 255, 255, 0.88);
49
+ text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
50
+ overflow: hidden;
51
+ text-overflow: ellipsis;
52
+ white-space: nowrap;
53
+ }
54
+ .window-controls {
55
+ display: flex;
56
+ height: 32px;
57
+ margin-right: 10px;
58
+ overflow: hidden;
59
+ border: 1px solid rgba(255, 255, 255, 0.12);
60
+ border-radius: 6px;
61
+ background: rgba(8, 12, 20, 0.38);
62
+ backdrop-filter: blur(10px);
63
+ pointer-events: auto;
64
+ -webkit-app-region: no-drag;
65
+ }
66
+ .window-btn {
67
+ width: 42px;
68
+ height: 32px;
69
+ display: inline-flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ border: 0;
73
+ border-right: 1px solid rgba(255, 255, 255, 0.1);
74
+ background: transparent;
75
+ color: rgba(255, 255, 255, 0.82);
76
+ font-size: 16px;
77
+ line-height: 1;
78
+ cursor: pointer;
79
+ transition: background 0.15s ease, color 0.15s ease;
80
+ }
81
+ .window-btn:last-child {
82
+ border-right: 0;
83
+ }
84
+ .window-btn:hover {
85
+ background: rgba(255, 255, 255, 0.14);
86
+ color: #fff;
87
+ }
88
+ .window-btn.close:hover {
89
+ background: #e5484d;
90
+ color: #fff;
91
+ }
92
+ #loading-overlay {
59
93
  position: absolute;
60
94
  top: 0;
61
95
  left: 0;
@@ -92,10 +126,16 @@
92
126
  <script src="./node_modules/hls.js/dist/hls.min.js"></script>
93
127
  <script src="./node_modules/artplayer/dist/artplayer.js"></script>
94
128
  </head>
95
- <body>
96
- <div class="drag-region"></div>
97
- <button id="close-btn" onclick="window.close()">✕ Đóng</button>
98
- <div id="loading-overlay">
129
+ <body>
130
+ <header id="top-nav">
131
+ <div class="nav-title" id="nav-title">NekoStream Player</div>
132
+ <div class="window-controls">
133
+ <button class="window-btn" id="window-minimize" title="Minimize">-</button>
134
+ <button class="window-btn" id="window-maximize" title="Maximize">□</button>
135
+ <button class="window-btn close" id="window-close" title="Close">×</button>
136
+ </div>
137
+ </header>
138
+ <div id="loading-overlay">
99
139
  <div class="spinner"></div>
100
140
  <div class="loading-text">Đang tải và làm sạch trình phát...</div>
101
141
  </div>
@@ -103,9 +143,19 @@
103
143
 
104
144
  <script>
105
145
  const { ipcRenderer } = require('electron');
106
- ipcRenderer.on('main-log', (e, msg) => {
107
- console.log('[Main Process]', msg);
108
- });
146
+ ipcRenderer.on('main-log', (e, msg) => {
147
+ console.log('[Main Process]', msg);
148
+ });
149
+
150
+ document.getElementById('window-minimize').addEventListener('click', () => {
151
+ ipcRenderer.send('player:minimize');
152
+ });
153
+ document.getElementById('window-maximize').addEventListener('click', () => {
154
+ ipcRenderer.send('player:toggle-maximize');
155
+ });
156
+ document.getElementById('window-close').addEventListener('click', () => {
157
+ window.close();
158
+ });
109
159
 
110
160
  // Keyboard shortcut: Escape to close
111
161
  document.addEventListener('keydown', (e) => {
@@ -113,8 +163,10 @@
113
163
  });
114
164
 
115
165
 
116
- window.initPlayer = function(streamInfo, baseDir, cleanUA) {
117
- const container = document.getElementById('player-container');
166
+ window.initPlayer = function(streamInfo, baseDir, cleanUA) {
167
+ const container = document.getElementById('player-container');
168
+ const navTitle = document.getElementById('nav-title');
169
+ navTitle.textContent = streamInfo.provider ? `NekoStream · ${streamInfo.provider}` : 'NekoStream Player';
118
170
 
119
171
  if (streamInfo.type === 'iframe') {
120
172
  const overlay = document.getElementById('loading-overlay');