525 lines
25 KiB
HTML
Executable File
525 lines
25 KiB
HTML
Executable File
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<title id="appTitle">Call-me</title>
|
|
|
|
<!-- Meta Information -->
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
|
|
/>
|
|
<!-- https://favicon.io/favicon-generator/ -->
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
|
|
<link rel="manifest" href="/favicon/site.webmanifest" />
|
|
|
|
<!-- https://ogp.me -->
|
|
<meta property="og:type" content="app-webrtc" />
|
|
<meta property="og:site_name" content="Call-me" />
|
|
<meta property="og:title" content="Click the link to make a call." />
|
|
<meta property="og:description" content="Your Go-To for Instant Video Calls!" />
|
|
<meta property="og:image" content="https://cme.mirotalk.com/assets/callme.png" />
|
|
<meta property="og:url" content="https://cme.mirotalk.com" />
|
|
|
|
<!-- Link to Bootstrap CSS -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css" />
|
|
|
|
<!-- Link to Font Awesome CSS for icons -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
|
|
|
|
<!-- Link to your custom CSS file -->
|
|
<link rel="stylesheet" href="./style.css" />
|
|
|
|
<!-- Link to SweetAlert CSS file -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11.4.8/dist/sweetalert2.min.css" />
|
|
|
|
<!-- ink to Animate CSS file -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css/animate.min.css" />
|
|
|
|
<!-- Link to Toastify CSS file -->
|
|
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css" />
|
|
</head>
|
|
|
|
<body>
|
|
<!-- The attribution text will be injected here -->
|
|
<p id="attribution"></p>
|
|
|
|
<!-- Optional Random BG Images -->
|
|
<img id="randomImage" src="background.jpg" alt="Random Background Image" />
|
|
|
|
<!-- GitHub project -->
|
|
<div id="githubDiv">
|
|
<a
|
|
class="github-button"
|
|
href="https://github.com/miroslavpejic85/call-me"
|
|
data-color-scheme="no-preference: light; light: light; dark: dark;"
|
|
data-size="large"
|
|
data-show-count="true"
|
|
aria-label="Star miroslavpejic85/call-me on GitHub"
|
|
>Star
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Sign-in Page -->
|
|
<div id="signInPage" class="container mt-5">
|
|
<div class="row justify-content-center">
|
|
<div class="col-md-6 col-lg-5 col-xl-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h1 id="appName" data-i18n="appName">Call-me</h1>
|
|
<p class="sign-in-subtitle" data-i18n="signIn.subtitle">
|
|
Instant Video Calls. No signup needed.
|
|
</p>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Sign-in Form -->
|
|
<div class="mb-3">
|
|
<!-- Input field for entering the username -->
|
|
<div class="username-input-wrapper">
|
|
<input
|
|
id="usernameIn"
|
|
type="text"
|
|
placeholder="Choose a display name"
|
|
data-i18n-placeholder="signIn.username"
|
|
required
|
|
/>
|
|
<button
|
|
id="randomUsernameBtn"
|
|
class="random-username-btn"
|
|
type="button"
|
|
title="Generate random username"
|
|
>
|
|
<i class="fas fa-random"></i>
|
|
</button>
|
|
<button
|
|
id="copyUsernameBtn"
|
|
class="copy-username-btn"
|
|
type="button"
|
|
title="Copy username"
|
|
>
|
|
<i class="fas fa-copy"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<!-- Media toggles -->
|
|
<div class="media-toggles mb-3">
|
|
<label class="media-toggle-item" for="joinAudioToggle">
|
|
<div class="media-toggle-icon">
|
|
<i class="fas fa-microphone"></i>
|
|
</div>
|
|
<span class="media-toggle-label" data-i18n="signIn.microphone">Microphone</span>
|
|
<div class="switch">
|
|
<input id="joinAudioToggle" type="checkbox" checked />
|
|
<span class="slider"></span>
|
|
</div>
|
|
</label>
|
|
<label class="media-toggle-item" for="joinVideoToggle">
|
|
<div class="media-toggle-icon">
|
|
<i class="fas fa-video"></i>
|
|
</div>
|
|
<span class="media-toggle-label" data-i18n="signIn.camera">Camera</span>
|
|
<div class="switch">
|
|
<input id="joinVideoToggle" type="checkbox" checked />
|
|
<span class="slider"></span>
|
|
</div>
|
|
</label>
|
|
</div>
|
|
<!-- Sign-in button -->
|
|
<button id="signInBtn" class="btn btn-primary" data-i18n="signIn.button">Join</button>
|
|
|
|
<!-- Direct call section -->
|
|
<div class="direct-call-section">
|
|
<div class="direct-call-divider">
|
|
<span data-i18n="signIn.directCallLabel">Or call someone directly</span>
|
|
</div>
|
|
<div class="direct-call-row">
|
|
<input
|
|
id="directCallInput"
|
|
type="text"
|
|
placeholder="Enter name to call"
|
|
data-i18n-placeholder="signIn.directCallPlaceholder"
|
|
autocomplete="off"
|
|
/>
|
|
<button id="directCallBtn" class="btn btn-call-now">
|
|
<i class="fas fa-phone"></i>
|
|
<span data-i18n="signIn.directCallButton">Call Now</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="privacy-divider">
|
|
<span><a href="/privacy" class="privacy-link">Privacy Policy</a></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Room Page -->
|
|
<div id="roomPage" class="container">
|
|
<!-- Session time -->
|
|
<span id="sessionTime">0s</span>
|
|
|
|
<!-- Calling overlay (outgoing) -->
|
|
<div id="callingOverlay" class="calling-overlay">
|
|
<div class="calling-overlay-content">
|
|
<div class="calling-pulse-ring"></div>
|
|
<i class="fas fa-phone calling-icon"></i>
|
|
<p class="calling-status" data-i18n="room.callingOverlay">Calling...</p>
|
|
<p id="callingUsername" class="calling-username"></p>
|
|
<span id="callingTimer" class="calling-timer">0s</span>
|
|
<button id="cancelCallBtn" class="btn btn-danger btn-cancel-call" data-i18n="room.cancelCall">
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Incoming call overlay -->
|
|
<div id="incomingCallOverlay" class="incoming-call-overlay">
|
|
<div class="incoming-call-content">
|
|
<div class="incoming-call-ring-outer"></div>
|
|
<div class="incoming-call-ring-inner"></div>
|
|
<div class="incoming-call-avatar">
|
|
<i class="fas fa-user"></i>
|
|
</div>
|
|
<p class="incoming-call-label" data-i18n="room.incomingCall">Incoming call</p>
|
|
<p id="incomingCallUsername" class="incoming-call-username"></p>
|
|
<div id="incomingCallTimer" class="incoming-call-timer"></div>
|
|
<div class="incoming-call-actions">
|
|
<button id="declineCallBtn" class="btn-call-action btn-decline" title="Decline">
|
|
<i class="fas fa-phone-slash"></i>
|
|
</button>
|
|
<button id="acceptCallBtn" class="btn-call-action btn-accept" title="Accept">
|
|
<i class="fas fa-phone"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Remote video container (video from the other user) -->
|
|
<div id="remoteVideoContainer">
|
|
<!-- Local video container (your video) -->
|
|
<div id="localVideoContainer">
|
|
<video id="localVideo"></video>
|
|
<span id="localUsername"></span>
|
|
</div>
|
|
<div id="streamStatusContainer">
|
|
<i id="remoteAudioDisabled" class="fas fa-microphone color-red hide"></i>
|
|
<i id="remoteVideoDisabled" class="fas fa-video color-red hide"></i>
|
|
</div>
|
|
<video id="remoteVideo"></video>
|
|
<span id="remoteUsername" class="hide"></span>
|
|
</div>
|
|
|
|
<div class="row justify-content-center">
|
|
<!-- Button share Room -->
|
|
<button
|
|
id="shareRoomBtn"
|
|
class="btn btn-custom btn-primary btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Share room"
|
|
data-i18n-title="controls.shareRoom"
|
|
>
|
|
<i class="fas fa-share-nodes"></i>
|
|
</button>
|
|
|
|
<!-- Button to toggle audio stream -->
|
|
<button
|
|
id="audioBtn"
|
|
class="btn btn-custom btn-success btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Toggle audio"
|
|
data-i18n-title="controls.toggleAudio"
|
|
>
|
|
<i class="fas fa-microphone"></i>
|
|
</button>
|
|
<!-- Button to toggle video stream -->
|
|
<button
|
|
id="videoBtn"
|
|
class="btn btn-custom btn-success btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Toggle video"
|
|
data-i18n-title="controls.toggleVideo"
|
|
>
|
|
<i class="fas fa-video"></i>
|
|
</button>
|
|
<!-- Button to swap camera -->
|
|
<button
|
|
id="swapCameraBtn"
|
|
class="btn btn-custom btn-success btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Swap camera"
|
|
data-i18n-title="controls.swapCamera"
|
|
>
|
|
<i class="fas fa-camera-rotate"></i>
|
|
</button>
|
|
<!-- Button to share screen -->
|
|
<button
|
|
id="screenShareBtn"
|
|
class="btn btn-custom btn-success btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Toggle screen"
|
|
data-i18n-title="controls.toggleScreen"
|
|
>
|
|
<i class="fas fa-desktop"></i>
|
|
</button>
|
|
<!-- Toggle user sidebar button -->
|
|
<button
|
|
id="sidebarBtn"
|
|
class="btn btn-custom btn-primary btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Toggle users"
|
|
data-i18n-title="controls.toggleUsers"
|
|
>
|
|
<i class="fas fa-users"></i>
|
|
<span id="participantCount" class="participant-count hidden">0</span>
|
|
<span id="messageCount" class="message-count hidden">0</span>
|
|
</button>
|
|
<!-- Button to leave the call -->
|
|
<button
|
|
id="leaveBtn"
|
|
class="btn btn-custom btn-danger btn-m"
|
|
data-toggle="tooltip"
|
|
data-placement="top"
|
|
title="Leave"
|
|
data-i18n-title="controls.leave"
|
|
>
|
|
<i class="fas fa-phone-slash red"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Sidebar with tabs for users and chat -->
|
|
<div id="userSidebar" class="user-sidebar">
|
|
<div class="user-sidebar-header">
|
|
<div class="sidebar-tabs">
|
|
<button
|
|
id="usersTab"
|
|
class="sidebar-tab active"
|
|
data-tab="users"
|
|
title="Users"
|
|
data-i18n-title="room.users"
|
|
data-toggle="tooltip"
|
|
data-placement="bottom"
|
|
>
|
|
<i class="fas fa-users"></i> <span data-i18n="room.users">Users</span>
|
|
</button>
|
|
<button
|
|
id="chatTab"
|
|
class="sidebar-tab"
|
|
data-tab="chat"
|
|
title="Chat"
|
|
data-i18n-title="room.chat"
|
|
data-toggle="tooltip"
|
|
data-placement="bottom"
|
|
>
|
|
<i class="fas fa-comments"></i> <span data-i18n="room.chat">Chat</span>
|
|
<span id="chatNotification" class="chat-notification hidden">0</span>
|
|
</button>
|
|
<button
|
|
id="settingsTab"
|
|
class="sidebar-tab"
|
|
data-tab="settings"
|
|
title="Settings"
|
|
data-i18n-title="settings.settings"
|
|
data-toggle="tooltip"
|
|
data-placement="bottom"
|
|
>
|
|
<i class="fas fa-cog"></i> <span data-i18n="settings.settings">Settings</span>
|
|
</button>
|
|
</div>
|
|
|
|
<button
|
|
id="exitSidebarBtn"
|
|
class="btn btn-exit-sidebar"
|
|
title="Close sidebar"
|
|
data-i18n-title="room.closeSidebar"
|
|
>
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Users Tab Content -->
|
|
<div id="usersContent" class="tab-content active">
|
|
<div class="user-search-bar">
|
|
<div class="user-search-wrapper">
|
|
<i class="fas fa-search"></i>
|
|
<input
|
|
type="text"
|
|
id="userSearchInput"
|
|
placeholder="Search users..."
|
|
data-i18n-placeholder="room.searchUsers"
|
|
autocomplete="off"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<ul id="userList" class="user-list"></ul>
|
|
</div>
|
|
|
|
<!-- Chat Tab Content -->
|
|
<div id="chatContent" class="tab-content">
|
|
<div id="chatMessages" class="chat-messages"></div>
|
|
<form id="chatForm" class="chat-form" autocomplete="off">
|
|
<button
|
|
type="button"
|
|
id="emojiBtn"
|
|
class="btn btn-emoji"
|
|
title="Add emoji"
|
|
data-i18n-title="chat.addEmoji"
|
|
>
|
|
<i class="fas fa-smile"></i>
|
|
</button>
|
|
<input
|
|
id="chatInput"
|
|
type="text"
|
|
placeholder="Type a message..."
|
|
data-i18n-placeholder="chat.typeMessage"
|
|
autocomplete="off"
|
|
/>
|
|
<button type="submit" class="btn btn-primary btn-send-chat" data-i18n-title="chat.sendMessage">
|
|
<i class="fas fa-paper-plane"></i>
|
|
</button>
|
|
</form>
|
|
<div id="emojiPicker" class="emoji-picker-container"></div>
|
|
</div>
|
|
|
|
<!-- Settings Tab Content -->
|
|
<div id="settingsContent" class="tab-content">
|
|
<div class="settings-section">
|
|
<h3 class="settings-title">
|
|
<i class="fas fa-globe"></i> <span data-i18n="settings.language">Language</span>
|
|
</h3>
|
|
|
|
<div class="setting-group">
|
|
<label for="languageSelect" class="setting-label">
|
|
<i class="fas fa-language"></i>
|
|
<span data-i18n="settings.selectLanguage">Select Language</span>
|
|
</label>
|
|
<select id="languageSelect" class="setting-select"></select>
|
|
</div>
|
|
|
|
<h3 class="settings-title">
|
|
<i class="fas fa-sliders-h"></i>
|
|
<span data-i18n="settings.generalTitle">General</span>
|
|
</h3>
|
|
|
|
<div class="setting-group setting-toggle-group">
|
|
<label for="hideLocalVideoToggle" class="setting-label">
|
|
<i class="fas fa-eye-slash"></i>
|
|
<span data-i18n="settings.hideLocalVideo">Hide Local Video</span>
|
|
</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="hideLocalVideoToggle" />
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
|
|
<div id="pushNotificationGroup" class="setting-group setting-toggle-group">
|
|
<label for="pushNotificationToggle" class="setting-label">
|
|
<i class="fas fa-bell"></i>
|
|
<span data-i18n="settings.pushNotifications">Push Notifications</span>
|
|
</label>
|
|
<div class="push-toggle-wrapper">
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="pushNotificationToggle" />
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
<button id="pushTestBtn" class="btn-setting" data-i18n="settings.testPush">Test</button>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 class="settings-title">
|
|
<i class="fas fa-video"></i> <span data-i18n="settings.mediaDevicesTitle">Media Devices</span>
|
|
</h3>
|
|
|
|
<div class="setting-group">
|
|
<label for="videoSelect" class="setting-label">
|
|
<i class="fas fa-camera"></i> <span data-i18n="settings.videoInput">Camera</span>
|
|
</label>
|
|
<select id="videoSelect" class="setting-select">
|
|
<option value="" data-i18n="settings.loadingCameras">Loading cameras...</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="setting-group">
|
|
<label for="audioSelect" class="setting-label">
|
|
<i class="fas fa-microphone"></i> <span data-i18n="settings.audioInput">Microphone</span>
|
|
</label>
|
|
<select id="audioSelect" class="setting-select">
|
|
<option value="" data-i18n="settings.loadingMicrophones">Loading microphones...</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="setting-group">
|
|
<label for="audioOutputSelect" class="setting-label">
|
|
<i class="fas fa-volume-up"></i> <span data-i18n="settings.audioOutput">Speaker</span>
|
|
</label>
|
|
<select id="audioOutputSelect" class="setting-select">
|
|
<option value="" data-i18n="settings.loadingSpeakers">Loading speakers...</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="settings-actions">
|
|
<button id="testDevicesBtn" class="btn btn-success btn-test-devices">
|
|
<i class="fas fa-play"></i> <span data-i18n="settings.testDevices">Test Devices</span>
|
|
</button>
|
|
<button id="refreshDevicesBtn" class="btn btn-secondary btn-refresh-devices">
|
|
<i class="fas fa-sync"></i> <span data-i18n="settings.refresh">Refresh</span>
|
|
</button>
|
|
</div>
|
|
|
|
<h3 class="settings-title">
|
|
<i class="fas fa-comments"></i>
|
|
<span data-i18n="settings.chatSettingsTitle">Chat Settings</span>
|
|
</h3>
|
|
<div class="settings-actions">
|
|
<button id="saveChatBtn" class="btn btn-success btn-save-chat">
|
|
<i class="fas fa-download"></i> <span data-i18n="settings.saveMessages">Save Messages</span>
|
|
</button>
|
|
<button id="clearChatBtn" class="btn btn-danger btn-clear-chat">
|
|
<i class="fas fa-trash"></i> <span data-i18n="settings.clearAll">Clear All</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- JavaScript libraries for WebSocket and custom client code -->
|
|
<script src="/socket.io/socket.io.js"></script>
|
|
<script src="config.js"></script>
|
|
<script src="i18n.js"></script>
|
|
<script src="client.js"></script>
|
|
|
|
<!-- Include UaParser -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/UAParser.js/1.0.37/ua-parser.min.js"></script>
|
|
|
|
<!-- Include Axios file -->
|
|
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
|
|
|
<!-- Include SweetAlert JS file -->
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.4.8/dist/sweetalert2.all.min.js"></script>
|
|
|
|
<!-- Include GitHub buttons -->
|
|
<script src="https://buttons.github.io/buttons.js"></script>
|
|
|
|
<!-- Include Emoji Mart for emoji picker -->
|
|
<script defer src="https://cdn.jsdelivr.net/npm/emoji-mart@latest/dist/browser.js"></script>
|
|
|
|
<!-- Include Toastify JS file -->
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
|
|
|
|
<!-- Bootstrap JS -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
</body>
|
|
</html>
|