Skip to content

Commit e6c1c64

Browse files
Merge pull request #5571 from nguyentrannhan/develop
Develop
2 parents 3318c7a + 1ffeaf2 commit e6c1c64

File tree

29 files changed

+242
-223
lines changed

29 files changed

+242
-223
lines changed

BUILD.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Docs Fix 401: Your Apple ID has been locked - Mezon
2+
3+
Error: HTTP status code: 401. Your Apple ID has been locked. Visit iForgot to reset your account (https://iforgot.apple.com), then generate a new app-specific password. Ensure that all authentication arguments are correct.
4+
5+
Step1: Access https://developer.apple.com/account/ to unlock
6+
note: Once you change your password, all App-Specific Passwords will be deleted.
7+
8+
Step2: Create an App-Specific Passwords with your Apple ID
9+
Access https://appleid.apple.com/
10+
=> App-Specific Passwords => Create Password
11+
12+
Step3: Update secrets on Github
13+
Access Repo on Github => change secret Apple App-Specific Password
14+
note: ID = account login

apps/chat/src/app/pages/channel/ChannelMessage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export const ChannelMessage: ChannelMessageComponent = ({
4848
messageReplyHighlight,
4949
message,
5050
previousMessage,
51-
isTopic
51+
isTopic = false
5252
}: Readonly<MessageProps>) => {
5353
const openEditMessageState = useSelector(selectOpenEditMessageState);
5454
const idMessageRefEdit = useSelector(selectIdMessageRefEdit);
@@ -67,7 +67,7 @@ export const ChannelMessage: ChannelMessageComponent = ({
6767

6868
const handleContextMenu = useCallback(
6969
(event: React.MouseEvent<HTMLElement>, props?: Partial<MessageContextMenuProps>) => {
70-
showMessageContextMenu(event, messageId, mode, props);
70+
showMessageContextMenu(event, messageId, mode, isTopic as boolean, props);
7171
},
7272
[showMessageContextMenu, messageId, mode]
7373
);

apps/chat/src/app/pages/topicDiscussion/TopicDiscussionBox.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '@mezon/store';
1515
import { useMezon } from '@mezon/transport';
1616
import { IMessageSendPayload, sleep } from '@mezon/utils';
17+
import isElectron from 'is-electron';
1718
import { ChannelStreamMode, ChannelType } from 'mezon-js';
1819
import { ApiMessageAttachment, ApiMessageMention, ApiMessageRef } from 'mezon-js/api.gen';
1920
import { ApiSdTopic, ApiSdTopicRequest } from 'mezon-js/dist/api.gen';
@@ -133,16 +134,18 @@ const TopicDiscussionBox = () => {
133134
return (
134135
<>
135136
{(isFetchMessageDone || firstMessageOfThisTopic) && (
136-
<MemoizedChannelMessages
137-
channelId={currentTopicId as string}
138-
clanId={currentClanId as string}
139-
type={ChannelType.CHANNEL_TYPE_TEXT}
140-
mode={ChannelStreamMode.STREAM_MODE_CHANNEL}
141-
isTopicBox
142-
topicId={currentTopicId}
143-
/>
137+
<div className={isElectron() ? 'h-[calc(100%_-_60px_-_80px)]' : 'h-full'}>
138+
<MemoizedChannelMessages
139+
channelId={currentTopicId as string}
140+
clanId={currentClanId as string}
141+
type={ChannelType.CHANNEL_TYPE_TEXT}
142+
mode={ChannelStreamMode.STREAM_MODE_CHANNEL}
143+
isTopicBox
144+
topicId={currentTopicId}
145+
/>
146+
</div>
144147
)}
145-
<div className="flex flex-col flex-1 justify-end">
148+
<div className="flex flex-col flex-1">
146149
<div className="flex-shrink-0 flex flex-col pb-4 px-4 dark:bg-bgPrimary bg-bgLightPrimary h-auto relative">
147150
<MentionReactInput
148151
onSend={handleSend}

apps/desktop/src/app/app.ts

Lines changed: 3 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1-
import { BrowserWindow, Menu, MenuItemConstructorOptions, Notification, app, ipcMain, screen, shell } from 'electron';
1+
import { BrowserWindow, Menu, MenuItemConstructorOptions, Notification, app, screen, shell } from 'electron';
22
import { autoUpdater } from 'electron-updater';
33
import activeWindows from 'mezon-active-windows';
44
import { join } from 'path';
55
import { format } from 'url';
6-
import { electronAppName, rendererAppName, rendererAppPort } from './constants';
6+
import { rendererAppName, rendererAppPort } from './constants';
77

88
import tray from '../Tray';
99
import setupAutoUpdates from './autoUpdates';
10-
import {
11-
ACTIVE_WINDOW,
12-
CHANGE_ATTACHMENT_LIST,
13-
GET_ATTACHMENT_DATA,
14-
SEND_ATTACHMENT_DATA,
15-
SET_ATTACHMENT_DATA,
16-
SET_CURRENT_IMAGE,
17-
TRIGGER_SHORTCUT
18-
} from './events/constants';
10+
import { ACTIVE_WINDOW, TRIGGER_SHORTCUT } from './events/constants';
1911
import setupRequestPermission from './requestPermission';
2012
import { initBadge } from './services/badge';
2113
import { forceQuit } from './utils';
@@ -259,96 +251,6 @@ export default class App {
259251
return window !== null && !window.isDestroyed();
260252
}
261253

262-
static openImageWindow(props: any, options?: Electron.BrowserWindowConstructorOptions, params?: Record<string, string>) {
263-
const defaultOptions: Electron.BrowserWindowConstructorOptions = {
264-
width: 1000,
265-
height: 800,
266-
backgroundColor: '#1a1a1a',
267-
show: false,
268-
titleBarStyle: 'hidden',
269-
frame: false,
270-
trafficLightPosition: process.platform == 'darwin' ? { x: -20, y: -20 } : undefined,
271-
webPreferences: {
272-
nodeIntegration: false,
273-
contextIsolation: true,
274-
preload: join(__dirname, 'main.preload.js'),
275-
backgroundThrottling: false
276-
},
277-
autoHideMenuBar: true,
278-
titleBarOverlay: false,
279-
paintWhenInitiallyHidden: true,
280-
visualEffectState: 'active'
281-
};
282-
283-
const windowOptions = { ...defaultOptions, ...options };
284-
285-
if (!this.isWindowValid(this.imageViewerWindow) && !this.listWindowOpen?.[IMAGE_WINDOW_KEY]) {
286-
this.imageViewerWindow = new BrowserWindow(windowOptions);
287-
this.listWindowOpen = {
288-
...this.listWindowOpen,
289-
[IMAGE_WINDOW_KEY]: this.imageViewerWindow
290-
};
291-
292-
const emptyMenu = Menu.buildFromTemplate([]);
293-
this.imageViewerWindow.setMenu(emptyMenu);
294-
this.imageViewerWindow.setMenuBarVisibility(false);
295-
// this.imageViewerWindow.setOpacity(0);
296-
297-
const filePath = App.application.isPackaged
298-
? 'assets/image-window/image-window.html'
299-
: 'apps/desktop/src/assets/image-window/image-window.html';
300-
const baseUrl = App.application.isPackaged
301-
? join(__dirname, '..', electronAppName, filePath)
302-
: join(__dirname, '..', '..', '..', filePath);
303-
const fullUrl = this.generateFullUrl(baseUrl, params);
304-
305-
const loadContent = async () => {
306-
try {
307-
this.imageViewerWindow.loadURL(
308-
format({
309-
pathname: fullUrl,
310-
protocol: 'file:',
311-
slashes: true,
312-
query: params
313-
})
314-
);
315-
} catch (error) {
316-
console.error('Failed to load window:', error);
317-
}
318-
};
319-
320-
loadContent();
321-
this.imageViewerWindow?.show();
322-
}
323-
324-
if (!App.application.isPackaged) {
325-
this.imageViewerWindow.webContents.removeAllListeners('did-fail-load');
326-
this.imageViewerWindow.webContents.on('did-fail-load', (_, code, description) => {
327-
console.error('Window load failed:', code, description);
328-
});
329-
}
330-
331-
this.imageViewerWindow?.setOpacity(1);
332-
this.imageViewerWindow.removeAllListeners('closed');
333-
this.imageViewerWindow.on('closed', () => {
334-
this.imageViewerWindow = null;
335-
delete this.listWindowOpen[IMAGE_WINDOW_KEY];
336-
});
337-
ipcMain.removeAllListeners(SEND_ATTACHMENT_DATA);
338-
ipcMain.on(SEND_ATTACHMENT_DATA, (event, data) => {
339-
this.attachmentData = data;
340-
this.imageViewerWindow.webContents.send(CHANGE_ATTACHMENT_LIST);
341-
});
342-
ipcMain.removeAllListeners(GET_ATTACHMENT_DATA);
343-
ipcMain.on(GET_ATTACHMENT_DATA, () => {
344-
this.imageViewerWindow.webContents.send(SET_CURRENT_IMAGE, props);
345-
this.imageViewerWindow.webContents.send(SET_ATTACHMENT_DATA, this.attachmentData);
346-
});
347-
this.imageViewerWindow?.focus();
348-
349-
return this.imageViewerWindow;
350-
}
351-
352254
/**
353255
* setup badge for the app
354256
*/

apps/desktop/src/assets/image-window/image-window-css.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ body {
141141
}
142142
143143
.thumbnail-container {
144-
width: fit-content;
144+
width : 112px;
145145
height: 100%;
146146
background-color: #0B0B0B;
147147
padding: 0 10px;
@@ -337,5 +337,6 @@ body {
337337
margin: 4px 0;
338338
}
339339
340+
340341
`;
341342
export default image_window_css;

apps/desktop/src/assets/image-window/update_window_image.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,55 @@ function updateImagePopup(imageData: ImageData, imageWindow: BrowserWindow) {
1515
document.getElementById('timestamp').innerHTML = "${time}"
1616
${scriptThumnails(imageData.channelImagesData.images, activeIndex)}
1717
`);
18+
19+
imageWindow.webContents.executeJavaScript(`
20+
document.addEventListener('keydown', (e) => {
21+
switch (e.key) {
22+
case 'ArrowUp':
23+
if(currentIndex > 0){
24+
document.querySelectorAll('.thumbnail').forEach(img => img.classList.remove('active'));
25+
currentIndex--;
26+
document.querySelectorAll('.thumbnail')[currentIndex].classList.add('active');
27+
document.querySelectorAll('.thumbnail')[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
28+
selectedImage.src = document.querySelectorAll('.thumbnail')[currentIndex].src;
29+
30+
}
31+
break;
32+
case 'ArrowLeft':
33+
if(currentIndex > 0){
34+
document.querySelectorAll('.thumbnail').forEach(img => img.classList.remove('active'));
35+
currentIndex--;
36+
document.querySelectorAll('.thumbnail')[currentIndex].classList.add('active');
37+
document.querySelectorAll('.thumbnail')[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
38+
document.querySelectorAll('.thumbnail')[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
39+
selectedImage.src = document.querySelectorAll('.thumbnail')[currentIndex].src;
40+
41+
}
42+
break;
43+
case 'ArrowDown':
44+
if(currentIndex < ${imageData.channelImagesData.images.length} - 1){
45+
document.querySelectorAll('.thumbnail').forEach(img => img.classList.remove('active'));
46+
currentIndex++;
47+
document.querySelectorAll('.thumbnail')[currentIndex].classList.add('active');
48+
document.querySelectorAll('.thumbnail')[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
49+
selectedImage.src = document.querySelectorAll('.thumbnail')[currentIndex].src;
50+
51+
}
52+
break;
53+
case 'ArrowRight':
54+
if(currentIndex < ${imageData.channelImagesData.images.length} - 1){
55+
currentIndex++;
56+
document.querySelectorAll('.thumbnail').forEach(img => img.classList.remove('active'));
57+
document.querySelectorAll('.thumbnail')[currentIndex].classList.add('active');
58+
document.querySelectorAll('.thumbnail')[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
59+
selectedImage.src = document.querySelectorAll('.thumbnail')[currentIndex].src;
60+
61+
}
62+
break;
63+
}
64+
});
65+
`);
66+
1867
imageWindow.focus();
1968
}
2069

apps/desktop/src/assets/image-window/window_image.ts

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ function openImagePopup(imageData: ImageData, parentWindow: BrowserWindow = App.
226226

227227
// Show window when ready with fade-in effect
228228
popupWindow.once('ready-to-show', () => {
229+
popupWindow.show();
229230
popupWindow.webContents.executeJavaScript(`
230231
231232
const selectedImage = document.getElementById('selectedImage');
@@ -234,7 +235,7 @@ function openImagePopup(imageData: ImageData, parentWindow: BrowserWindow = App.
234235
url : '${imageData.url}',
235236
realUrl : '${imageData.realUrl}'
236237
};
237-
238+
let currentIndex = ${activeIndex}
238239
document.getElementById('close-window').addEventListener('click', () => {
239240
selectedImage.src = null;
240241
window.electron.send('APP::IMAGE_WINDOW_TITLE_BAR_ACTION', 'APP::CLOSE_APP');
@@ -255,27 +256,13 @@ window.electron.handleActionShowImage('saveImage',currentImageUrl.url);
255256
256257
document.addEventListener('keydown', (e) => {
257258
switch (e.key) {
258-
case 'ArrowUp':
259-
navigateImage(-1);
260-
break;
261-
case 'ArrowLeft':
262-
navigateImage(-1);
263-
break;
264-
case 'ArrowDown':
265-
navigateImage(1);
266-
break;
267-
case 'ArrowRight':
268-
navigateImage(1);
269-
break;
270259
case 'Escape':
271260
selectedImage.src = null;
272261
window.electron.send('APP::IMAGE_WINDOW_TITLE_BAR_ACTION', 'APP::CLOSE_APP');
273262
break;
274263
}
275264
});
276265
277-
278-
${scriptThumnails(imageData.channelImagesData.images, activeIndex)}
279266
${scriptRotateAndZoom()}
280267
${scriptDrag()}
281268
@@ -291,10 +278,6 @@ document.addEventListener('keydown', (e) => {
291278
`);
292279
});
293280

294-
popupWindow.webContents.on('did-finish-load', () => {
295-
popupWindow.show();
296-
});
297-
298281
// Clean up on close
299282
popupWindow.on('closed', () => {
300283
ipcMain.removeHandler('minimize-window');
@@ -305,14 +288,6 @@ document.addEventListener('keydown', (e) => {
305288
return popupWindow;
306289
}
307290

308-
const generateQueryString = (params: Record<string, string>): string => {
309-
return Object.keys(params)
310-
.map((key) => {
311-
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
312-
})
313-
.join('&');
314-
};
315-
316291
function formatDate(dateString) {
317292
return new Date(dateString).toLocaleDateString();
318293
}
@@ -348,6 +323,7 @@ export const scriptThumnails = (listImage, indexSelect) => {
348323
selectedImage.src = '${image.url}';
349324
document.querySelectorAll('.thumbnail').forEach(img => img.classList.remove('active'));
350325
document.getElementById('thumbnail-${index}').querySelector('.thumbnail').classList.add('active');
326+
document.getElementById('thumbnail-${index}').querySelector('.thumbnail').scrollIntoView({ behavior: 'smooth', block: 'center' })
351327
document.getElementById('userAvatar').src = "${image.uploaderData.avatar}"
352328
document.getElementById('username').innerHTML = "${image.uploaderData.name}"
353329
document.getElementById('timestamp').innerHTML = "${time}"
@@ -357,6 +333,7 @@ export const scriptThumnails = (listImage, indexSelect) => {
357333
realUrl : '${image.realUrl || ''}'
358334
}
359335
336+
currentIndex = ${index}
360337
});`;
361338
})
362339
.join('');
@@ -476,22 +453,13 @@ document.addEventListener('contextmenu', (e) => {
476453
if (!e.currentTarget) return;
477454
478455
switch (action) {
479-
case 'copyLink': {
480-
window.electron.handleActionShowImage(action, selectedImage.src);
481-
break;
482-
}
483-
case 'openLink': {
484-
window.electron.shell.openExternal(selectedImage.src);
485-
break;
486-
}
487456
case 'copyImage': {
488457
window.electron.handleActionShowImage(action,currentImageUrl.realUrl );
489458
break;
490459
}
491-
case 'saveImage': {
492-
window.electron.handleActionShowImage(action, selectedImage.src);
460+
default :
461+
window.electron.handleActionShowImage(action, selectedImage.src);
493462
break;
494-
}
495463
}
496464
if (!menu) return;
497465
menu.classList.remove('visible');

apps/desktop/src/main.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ ipcMain.handle(ACTION_SHOW_IMAGE, async (event, action, data) => {
201201
clipboard.writeText(fileURL);
202202
break;
203203
}
204+
case 'openLink': {
205+
shell.openExternal(fileURL);
206+
break;
207+
}
204208
case 'copyImage': {
205209
const blobImage = await fetch(fileURL).then((response) => response.blob());
206210
const base64data = await blobImage.arrayBuffer();

0 commit comments

Comments
 (0)