mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Adapt the web version to Electron
This commit is contained in:
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
export type Platform = "win32" | "darwin" | "linux"
|
||||
|
||||
export interface ElectronInterface {
|
||||
desktop: true,
|
||||
platform: Platform
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
electronInterface: ElectronInterface
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,21 @@
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
import path from "node:path";
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({
|
||||
title: 'Main window',
|
||||
minWidth: 650,
|
||||
minHeight: 420
|
||||
minHeight: 420,
|
||||
webPreferences: {
|
||||
preload: path.join(import.meta.dirname, "preload.mjs")
|
||||
},
|
||||
titleBarStyle: "hidden",
|
||||
...(process.platform !== 'darwin' ? { titleBarOverlay: true } : {}),
|
||||
trafficLightPosition: {
|
||||
x: 16 - 4,
|
||||
y: 16 - 4
|
||||
},
|
||||
titleBarOverlay: process.platform !== "darwin"
|
||||
})
|
||||
|
||||
// You can use `process.env.VITE_DEV_SERVER_URL` when the vite command is called `serve`
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { contextBridge } from "electron";
|
||||
import type { ElectronInterface, Platform } from "../electron";
|
||||
|
||||
const electronInterface: ElectronInterface = {
|
||||
desktop: true,
|
||||
platform: process.platform as Platform
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld("electronInterface", electronInterface);
|
||||
+183
-171
@@ -7,185 +7,197 @@
|
||||
<link rel="icon" href="./src/images/logo.png" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- Login Form -->
|
||||
<div id="login-form" class="auth-container">
|
||||
<div class="auth-card fade-in">
|
||||
<div class="auth-header">
|
||||
<h2>
|
||||
<span class="material-symbols filled large">login</span>
|
||||
Добро пожаловать!
|
||||
</h2>
|
||||
<p>Войдите в свой аккаунт</p>
|
||||
</div>
|
||||
<div class="auth-body">
|
||||
<div id="login-alerts"></div>
|
||||
|
||||
<form id="login-form-element">
|
||||
<mdui-text-field
|
||||
label="Имя пользователя"
|
||||
id="login-username"
|
||||
name="username"
|
||||
variant="outlined"
|
||||
icon="person--filled"
|
||||
autocomplete="username"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
<mdui-text-field
|
||||
label="Пароль"
|
||||
id="login-password"
|
||||
name="password"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
toggle-password
|
||||
icon="password--filled"
|
||||
autocomplete="current-password"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
|
||||
<mdui-button type="submit">Войти</mdui-button>
|
||||
</form>
|
||||
|
||||
<div class="text-center">
|
||||
<p>Ещё нет аккаунта? <a href="#" id="register-link" class="link">Зарегистрируйтесь</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="electron-title-bar">
|
||||
<div class="macos-padding"></div>
|
||||
<div id="window-title"></div>
|
||||
<!-- <div class="window-controls">
|
||||
<mdui-button-icon icon="remove" id="window-minimize"></mdui-button-icon>
|
||||
<mdui-button-icon icon="stack--outlined" id="window-restore" class="hidden"></mdui-button-icon>
|
||||
<mdui-button-icon icon="ad--outlined" id="window-maximize"></mdui-button-icon>
|
||||
<mdui-button-icon icon="close" id="window-close"></mdui-button-icon>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<!-- Register Form -->
|
||||
<div id="register-form" class="auth-container" style="display: none;">
|
||||
<div class="auth-card fade-in">
|
||||
<div class="auth-header">
|
||||
<h2>
|
||||
<span class="material-symbols filled large">person_add</span>
|
||||
Регистрация
|
||||
</h2>
|
||||
<p>Создайте новый аккаунт</p>
|
||||
</div>
|
||||
<div class="auth-body">
|
||||
<div id="register-alerts"></div>
|
||||
|
||||
<form id="register-form-element">
|
||||
<mdui-text-field
|
||||
label="Имя пользователя"
|
||||
id="register-username"
|
||||
name="username"
|
||||
variant="outlined"
|
||||
icon="person--filled"
|
||||
autocomplete="username"
|
||||
maxlength="20"
|
||||
counter
|
||||
required>
|
||||
</mdui-text-field>
|
||||
<mdui-text-field
|
||||
label="Пароль"
|
||||
id="register-password"
|
||||
name="password"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
toggle-password
|
||||
icon="password--filled"
|
||||
autocomplete="new-password"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
<mdui-text-field
|
||||
label="Подтвердите пароль"
|
||||
id="register-confirm-password"
|
||||
name="confirm_password"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
toggle-password
|
||||
icon="password--filled"
|
||||
autocomplete="new-password"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
|
||||
<mdui-button type="submit">Зарегистрироваться</mdui-button>
|
||||
</form>
|
||||
|
||||
<div class="text-center">
|
||||
<p>
|
||||
Уже есть аккаунт?
|
||||
<a href="#" id="login-link" class="link">Войдите</a>
|
||||
</p>
|
||||
<div id="main-wrapper">
|
||||
<!-- Login Form -->
|
||||
<div id="login-form" class="auth-container">
|
||||
<div class="auth-card fade-in">
|
||||
<div class="auth-header">
|
||||
<h2>
|
||||
<span class="material-symbols filled large">login</span>
|
||||
Добро пожаловать!
|
||||
</h2>
|
||||
<p>Войдите в свой аккаунт</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="auth-body">
|
||||
<div id="login-alerts"></div>
|
||||
|
||||
<form id="login-form-element">
|
||||
<mdui-text-field
|
||||
label="Имя пользователя"
|
||||
id="login-username"
|
||||
name="username"
|
||||
variant="outlined"
|
||||
icon="person--filled"
|
||||
autocomplete="username"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
<mdui-text-field
|
||||
label="Пароль"
|
||||
id="login-password"
|
||||
name="password"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
toggle-password
|
||||
icon="password--filled"
|
||||
autocomplete="current-password"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
|
||||
<!-- Chat Interface -->
|
||||
<div id="chat-interface" style="display: none;">
|
||||
<div class="all-container">
|
||||
<div class="chat-list" id="chat-list">
|
||||
<header class="chat-header-left">
|
||||
<div id="productname">Loading...</div>
|
||||
<div class="profile">
|
||||
<a href="#" id="profile-open">
|
||||
<img src="./src/images/default-avatar.png" alt="" id="preview1" />
|
||||
</a>
|
||||
<mdui-button type="submit">Войти</mdui-button>
|
||||
</form>
|
||||
|
||||
<div class="text-center">
|
||||
<p>Ещё нет аккаунта? <a href="#" id="register-link" class="link">Зарегистрируйтесь</a></p>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-tabs">
|
||||
<mdui-tabs value="chats" full-width>
|
||||
<mdui-tab value="chats">
|
||||
Чаты
|
||||
</mdui-tab>
|
||||
<mdui-tab value="channels">
|
||||
Каналы
|
||||
</mdui-tab>
|
||||
<mdui-tab value="contacts">
|
||||
Контакты
|
||||
</mdui-tab>
|
||||
|
||||
<mdui-tab-panel slot="panel" value="chats">
|
||||
<mdui-list>
|
||||
<mdui-list-item headline="Общий чат" description="Вы: Последнее сообщение" id="chat-list-chat-1">
|
||||
<img src="./src/images/default-avatar.png" alt="" slot="icon" />
|
||||
</mdui-list-item>
|
||||
<mdui-list-item headline="Общий чат 2" description="Вы: Последнее сообщение" id="chat-list-chat-2">
|
||||
<img src="./src/images/default-avatar.png" alt="" slot="icon" />
|
||||
</mdui-list-item>
|
||||
</mdui-list>
|
||||
</mdui-tab-panel>
|
||||
<mdui-tab-panel slot="panel" value="channels">Скоро будет...</mdui-tab-panel>
|
||||
<mdui-tab-panel slot="panel" value="contacts">Скоро будет...</mdui-tab-panel>
|
||||
</mdui-tabs>
|
||||
</div>
|
||||
<mdui-bottom-app-bar>
|
||||
<mdui-button-icon icon="settings--filled" id="settings-open"></mdui-button-icon>
|
||||
<mdui-button-icon icon="group_add--filled"></mdui-button-icon>
|
||||
<div style="flex-grow: 1"></div>
|
||||
<mdui-fab icon="edit--filled"></mdui-fab>
|
||||
</mdui-bottom-app-bar>
|
||||
</div>
|
||||
<div class="chat-container">
|
||||
<div class="chat-main" id="chat-inner">
|
||||
<div class="chat-header">
|
||||
<img src="src/images/default-avatar.png" alt="Avatar" class="chat-header-avatar">
|
||||
<div class="chat-header-info">
|
||||
<div class="info-chat">
|
||||
<h4 id="chat-name">Общий чат</h4>
|
||||
<p>
|
||||
<span class="online-status"></span>
|
||||
Онлайн
|
||||
</p>
|
||||
</div>
|
||||
<a href="#" id="hide-chat">Свернуть чат</a>
|
||||
</div>
|
||||
|
||||
<!-- Register Form -->
|
||||
<div id="register-form" class="auth-container" style="display: none;">
|
||||
<div class="auth-card fade-in">
|
||||
<div class="auth-header">
|
||||
<h2>
|
||||
<span class="material-symbols filled large">person_add</span>
|
||||
Регистрация
|
||||
</h2>
|
||||
<p>Создайте новый аккаунт</p>
|
||||
</div>
|
||||
<div class="auth-body">
|
||||
<div id="register-alerts"></div>
|
||||
|
||||
<form id="register-form-element">
|
||||
<mdui-text-field
|
||||
label="Имя пользователя"
|
||||
id="register-username"
|
||||
name="username"
|
||||
variant="outlined"
|
||||
icon="person--filled"
|
||||
autocomplete="username"
|
||||
maxlength="20"
|
||||
counter
|
||||
required>
|
||||
</mdui-text-field>
|
||||
<mdui-text-field
|
||||
label="Пароль"
|
||||
id="register-password"
|
||||
name="password"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
toggle-password
|
||||
icon="password--filled"
|
||||
autocomplete="new-password"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
<mdui-text-field
|
||||
label="Подтвердите пароль"
|
||||
id="register-confirm-password"
|
||||
name="confirm_password"
|
||||
variant="outlined"
|
||||
type="password"
|
||||
toggle-password
|
||||
icon="password--filled"
|
||||
autocomplete="new-password"
|
||||
required>
|
||||
</mdui-text-field>
|
||||
|
||||
<mdui-button type="submit">Зарегистрироваться</mdui-button>
|
||||
</form>
|
||||
|
||||
<div class="text-center">
|
||||
<p>
|
||||
Уже есть аккаунт?
|
||||
<a href="#" id="login-link" class="link">Войдите</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat Interface -->
|
||||
<div id="chat-interface" style="display: none;">
|
||||
<div class="all-container">
|
||||
<div class="chat-list" id="chat-list">
|
||||
<header class="chat-header-left">
|
||||
<div id="productname">Loading...</div>
|
||||
<div class="profile">
|
||||
<a href="#" id="profile-open">
|
||||
<img src="./src/images/default-avatar.png" alt="" id="preview1" />
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-tabs">
|
||||
<mdui-tabs value="chats" full-width>
|
||||
<mdui-tab value="chats">
|
||||
Чаты
|
||||
</mdui-tab>
|
||||
<mdui-tab value="channels">
|
||||
Каналы
|
||||
</mdui-tab>
|
||||
<mdui-tab value="contacts">
|
||||
Контакты
|
||||
</mdui-tab>
|
||||
|
||||
<mdui-tab-panel slot="panel" value="chats">
|
||||
<mdui-list>
|
||||
<mdui-list-item headline="Общий чат" description="Вы: Последнее сообщение" id="chat-list-chat-1">
|
||||
<img src="./src/images/default-avatar.png" alt="" slot="icon" />
|
||||
</mdui-list-item>
|
||||
<mdui-list-item headline="Общий чат 2" description="Вы: Последнее сообщение" id="chat-list-chat-2">
|
||||
<img src="./src/images/default-avatar.png" alt="" slot="icon" />
|
||||
</mdui-list-item>
|
||||
</mdui-list>
|
||||
</mdui-tab-panel>
|
||||
<mdui-tab-panel slot="panel" value="channels">Скоро будет...</mdui-tab-panel>
|
||||
<mdui-tab-panel slot="panel" value="contacts">Скоро будет...</mdui-tab-panel>
|
||||
</mdui-tabs>
|
||||
</div>
|
||||
|
||||
<div class="chat-messages" id="chat-messages">
|
||||
<!-- Messages will be loaded here dynamically -->
|
||||
</div>
|
||||
|
||||
<div class="chat-input-wrapper">
|
||||
<div class="chat-input">
|
||||
<form class="input-group" id="message-form">
|
||||
<input type="text" class="message-input" id="message-input" placeholder="Напишите сообщение..." autocomplete="off">
|
||||
<button type="submit" class="send-btn">
|
||||
<span class="material-symbols filled">send</span>
|
||||
</button>
|
||||
</form>
|
||||
<mdui-bottom-app-bar>
|
||||
<mdui-button-icon icon="settings--filled" id="settings-open"></mdui-button-icon>
|
||||
<mdui-button-icon icon="group_add--filled"></mdui-button-icon>
|
||||
<div style="flex-grow: 1"></div>
|
||||
<mdui-fab icon="edit--filled"></mdui-fab>
|
||||
</mdui-bottom-app-bar>
|
||||
</div>
|
||||
<div class="chat-container">
|
||||
<div class="chat-main" id="chat-inner">
|
||||
<div class="chat-header">
|
||||
<img src="src/images/default-avatar.png" alt="Avatar" class="chat-header-avatar">
|
||||
<div class="chat-header-info">
|
||||
<div class="info-chat">
|
||||
<h4 id="chat-name">Общий чат</h4>
|
||||
<p>
|
||||
<span class="online-status"></span>
|
||||
Онлайн
|
||||
</p>
|
||||
</div>
|
||||
<a href="#" id="hide-chat">Свернуть чат</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chat-messages" id="chat-messages">
|
||||
<!-- Messages will be loaded here dynamically -->
|
||||
</div>
|
||||
|
||||
<div class="chat-input-wrapper">
|
||||
<div class="chat-input">
|
||||
<form class="input-group" id="message-form">
|
||||
<input type="text" class="message-input" id="message-input" placeholder="Напишите сообщение..." autocomplete="off">
|
||||
<button type="submit" class="send-btn">
|
||||
<span class="material-symbols filled">send</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -55,6 +55,7 @@ export function showLogin(): void {
|
||||
document.getElementById('register-form')!.style.display = 'none';
|
||||
document.getElementById('chat-interface')!.style.display = 'none';
|
||||
clearAlerts();
|
||||
document.getElementById("electron-title-bar")!.classList.add("color-surface");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +69,7 @@ export function showRegister(): void {
|
||||
document.getElementById('register-form')!.style.display = 'flex';
|
||||
document.getElementById('chat-interface')!.style.display = 'none';
|
||||
clearAlerts();
|
||||
document.getElementById("electron-title-bar")!.classList.add("color-surface");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,6 +83,7 @@ export function showChat(): void {
|
||||
document.getElementById('register-form')!.style.display = 'none';
|
||||
document.getElementById('chat-interface')!.style.display = 'block';
|
||||
loadMessages();
|
||||
document.getElementById("electron-title-bar")!.classList.remove("color-surface");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
height: 100%;
|
||||
padding: 2rem;
|
||||
background-color: $color-dark-surface;
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
@use "common/material" as *;
|
||||
|
||||
#chat-interface {
|
||||
height: 100%;
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
background-color: $color-dark-surface-container;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
@use "common/material" as *;
|
||||
|
||||
#electron-title-bar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.electron {
|
||||
#electron-title-bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 8px;
|
||||
height: 40px;
|
||||
background-color: $color-dark-surface-container;
|
||||
width: 100%;
|
||||
-webkit-app-region: drag;
|
||||
user-select: none;
|
||||
z-index: 10;
|
||||
transition: background-color 0.5s ease;
|
||||
|
||||
&.color-surface {
|
||||
background-color: $color-dark-surface;
|
||||
}
|
||||
}
|
||||
|
||||
#window-title {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&.platform-darwin .macos-padding {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
// .window-controls {
|
||||
// -webkit-app-region: no-drag;
|
||||
|
||||
// .hidden {
|
||||
// display: none;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#profile {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
@use "common/components";
|
||||
@use "common/colors" as *;
|
||||
@use "common/material" as *;
|
||||
@use "electron";
|
||||
|
||||
@use "lib/fonts/montserrat";
|
||||
@use "lib/fonts/material-symbols";
|
||||
@@ -24,6 +25,13 @@ body {
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
#main-wrapper {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
mdui-dialog {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import "../electron.d.ts";
|
||||
import { PRODUCT_NAME } from "./config";
|
||||
|
||||
if (window.electronInterface !== undefined) {
|
||||
console.log("Running in Electron");
|
||||
document.documentElement.classList.add("electron", `platform-${window.electronInterface.platform}`);
|
||||
document.getElementById("window-title")!.textContent = PRODUCT_NAME;
|
||||
} else {
|
||||
console.log("Running in normal browser");
|
||||
}
|
||||
@@ -15,4 +15,5 @@ import "./leftpanel";
|
||||
import "./init";
|
||||
import "./profile";
|
||||
import "./message-context-menu";
|
||||
import "./user-profile-dialog";
|
||||
import "./user-profile-dialog";
|
||||
import "./electron";
|
||||
Reference in New Issue
Block a user