rustream/templates/
landing.rs1pub fn get_content() -> String {
11 r###"<!DOCTYPE html>
12<!--suppress JSUnresolvedLibraryURL -->
13<html lang="en">
14<head>
15 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
16 {% if media_title %}
17 <title>{{ media_title }}</title>
18 {% else %}
19 <title>RuStream - Self-hosted Streaming Engine - v{{ version }}</title>
20 {% endif %}
21 <meta property="og:type" content="MediaStreaming">
22 <meta name="keywords" content="Rust, streaming, actix, JavaScript, HTML, CSS">
23 <meta name="author" content="Vignesh Rao">
24 <meta content="width=device-width, initial-scale=1" name="viewport">
25 <!-- CSS and JS for video-js plugin -->
26 <!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
27 <!-- <script src="https://thevickypedia.github.io/open-source/videojs/videojs-ie8.js"></script> -->
28 <link href="https://thevickypedia.github.io/open-source/videojs/video.css" rel="stylesheet"/>
29 <script src="https://thevickypedia.github.io/open-source/videojs/video.js" defer></script>
30 <!-- Favicon.ico and Apple Touch Icon -->
31 <link rel="icon" href="https://thevickypedia.github.io/open-source/images/logo/actix.ico">
32 <link rel="apple-touch-icon" href="https://thevickypedia.github.io/open-source/images/logo/actix.png">
33 <!-- Font Awesome icons -->
34 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/fontawesome.min.css">
35 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/solid.css">
36 <!-- Button CSS -->
37 <style>
38 /* Google fonts with a backup alternative */
39 @import url('https://fonts.googleapis.com/css2?family=Ubuntu:wght@400;500;700&display=swap');
40 * {
41 font-family: 'Ubuntu', 'PT Serif', sans-serif;
42 }
43 .iter {
44 border: none;
45 padding: 10px 14px;
46 font-size: 16px;
47 cursor: pointer;
48 }
49 .upload {
50 position: absolute;
51 top: 3.8%;
52 right: 313px;
53 border: none;
54 padding: 10px 14px;
55 font-size: 16px;
56 cursor: pointer;
57 }
58 .home {
59 position: absolute;
60 top: 3.8%;
61 right: 217px;
62 border: none;
63 padding: 10px 14px;
64 font-size: 16px;
65 cursor: pointer;
66 }
67 .back {
68 position: absolute;
69 top: 3.8%;
70 right: 132px;
71 border: none;
72 padding: 10px 14px;
73 font-size: 16px;
74 cursor: pointer;
75 }
76 body {
77 background-color: #151515;
78 }
79 title, h1, h2, h3, h4, h5, h6, p, a {
80 color: #f0f0f0;
81 }
82 button {
83 background: transparent !important;
84 color: #f0f0f0;
85 }
86 button:hover {
87 background: transparent !important;
88 opacity: 0.6;
89 transition: 0.5s;
90 }
91 </style>
92 <!-- Container, title and body CSS -->
93 <style>
94 h1 {
95 text-align: center;
96 }
97 </style>
98 <!-- Size of the container and the player -->
99 <style>
100 body {
101 margin: 0; /* Remove default margin */
102 padding: 0; /* Remove default padding */
103 box-sizing: border-box; /* Include padding and border in element's total width and height */
104 }
105 #content-container {
106 position: relative;
107 width: 70%;
108 max-width: 100%; /* Set a maximum width to prevent overflow */
109 height: 75vh; /* Set height to 75% of the viewport height */
110 margin: 0 auto; /* Center the container horizontally */
111 }
112 #nav-container {
113 position: relative;
114 width: 70%;
115 margin: 0 auto; /* Center the container horizontally */
116 }
117 #image-source {
118 max-width: 100%;
119 height: 75vh;
120 margin: 0 auto; /* Center the container horizontally */
121 display: flex;
122 justify-content: center;
123 align-items: center; /* Center the container vertically */
124 cursor: pointer; /* Add a pointer cursor to indicate it's clickable */
125 overflow: hidden; /* Avoid vertical overflow */
126 }
127 #video-player {
128 position: relative;
129 height: 100%;
130 width: 100%;
131 display: block;
132 }
133 @media (max-width: 768px) {
134 #image-source {
135 height: auto;
136 width: 90%;
137 }
138 /* video-js plugin defaults to 120% on mobile phones, so use the same */
139 #content-container {
140 height: auto;
141 width: 120%;
142 }
143 #video-player {
144 height: auto;
145 width: 120%;
146 }
147 }
148 </style>
149 <style>
150 .dropbtn {
151 position: absolute;
152 top: 3.8%;
153 right: 30px;
154 padding: 10px 24px;
155 font-size: 16px;
156 border: none;
157 cursor: pointer;
158 }
159 .dropdown {
160 position: absolute;
161 top: 3.8%;
162 right: 30px;
163 padding: 10px 24px;
164 display: inline-block;
165 }
166 .dropdown-content {
167 display: none;
168 position: absolute;
169 top: 40px; /* Distance from the user icon button */
170 right: 30px;
171 width: 160px;
172 min-width: auto;
173 box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2); /* Basically, black with 20% opacity */
174 z-index: 1;
175 }
176 .dropdown-content a {
177 padding: 12px 16px;
178 text-decoration: none;
179 display: block;
180 }
181 .dropdown:hover .dropdown-content {display: block;}
182 </style>
183 <noscript>
184 <style>
185 body {
186 width: 100%;
187 height: 100%;
188 overflow: hidden;
189 }
190 </style>
191 <div style="position: fixed; text-align:center; height: 100%; width: 100%; background-color: #151515;">
192 <h2 style="margin-top:5%">This page requires JavaScript
193 to be enabled.
194 <br><br>
195 Please refer <a href="https://www.enable-javascript.com/">enable-javascript</a> for how to.
196 </h2>
197 <form>
198 <button type="submit" onClick="<meta httpEquiv='refresh' content='0'>">RETRY</button>
199 </form>
200 </div>
201 </noscript>
202</head>
203<body>
204 <button class="upload" onclick="upload()"><i class="fa-solid fa-cloud-arrow-up"></i> Upload</button>
205 <button class="home" onclick="goHome()"><i class="fa fa-home"></i> Home</button>
206 <button class="back" onclick="goBack()"><i class="fa fa-backward"></i> Back</button>
207 <div class="dropdown">
208 <button class="dropbtn"><i class="fa fa-user"></i></button>
209 <div class="dropdown-content">
210 <a onclick="goProfile()" style="cursor: pointer;"><i class="fa-solid fa-user-lock"></i> {{ user }}</a>
211 <a onclick="logOut()" style="cursor: pointer"><i class="fa fa-sign-out"></i> logout</a>
212 </div>
213 </div>
214 <br><br><br>
215 <h1>{{ media_title }}</h1>
216 {% if render_image %}
217 <img id="image-source" src="" onclick="fullScreen()">
218 {% else %}
219 <div id="content-container">
220 <video id="video-player"
221 class="video-js"
222 preload="auto"
223 controls muted="muted"
224 style="position: relative; margin-left: auto; margin-right: auto; display: block"
225 data-setup='{
226 "playbackRates": [1, 1.5, 2, 5],
227 "controlBar": {
228 "skipButtons": {
229 "backward": 10,
230 "forward": 10
231 }
232 }
233 }'>
234 <source id="video-source" type="video/mp4" src=""/>
235 <track id="subtitles" kind="subtitles" src="" srclang="en"/>
236 <p class="vjs-no-js">
237 To view this video please enable JavaScript, and consider upgrading to a
238 web browser that
239 <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
240 </p>
241 </video>
242 </div>
243 {% endif %}
244 <div id="nav-container">
245 {% if previous %}
246 <button class="iter" style="float: left" onclick="window.location='{{ previous }}'" title="{{ previous }}">
247 <i class="fa fa-backward"></i> Previous
248 </button>
249 {% endif %}
250 {% if next %}
251 <button class="iter" style="float: right" onclick="window.location='{{ next }}'" title="{{ next }}">
252 Next <i class="fa fa-forward"></i>
253 </button>
254 {% endif %}
255 <br><br>
256 </div>
257 <script>
258 let origin = window.location.origin; // Get the current origin using JavaScript
259 let path = "{{ path }}";
260 {% if render_image %}
261 // Construct the source URL for the image by combining origin and path
262 let imageSource = origin + path;
263
264 // Set the image source URL for the image-source element
265 let imageElement = document.getElementById("image-source");
266 imageElement.setAttribute("src", imageSource);
267 {% else %}
268 let track = "{{ track }}";
269
270 // Construct the source URL for video by combining origin and path
271 let videoSource = origin + path;
272
273 // Set the video source URL for the video-source element
274 let videoElement = document.getElementById("video-source");
275 videoElement.setAttribute("src", videoSource);
276
277 // Set the subtitles URL for the video
278 let trackElement = document.getElementById("subtitles");
279 trackElement.setAttribute("src", track);
280
281 let videoPlayer = document.getElementById("video-player");
282 videoPlayer.load(); // Load the video
283 // videoPlayer.play(); // Play the video
284 {% endif %}
285 </script>
286 <script>
287 function goHome() {
288 window.location.href = "/home";
289 }
290 function goProfile() {
291 window.location.href = '/profile';
292 }
293 function logOut() {
294 window.location.href = "/logout";
295 }
296 function upload() {
297 window.location.href = "/upload";
298 }
299 function goBack() {
300 window.history.back();
301 }
302 </script>
303 <script>
304 function fullScreen() {
305 var doc = window.document;
306 // var docEl = doc.documentElement; // Entire container as fullScreen
307 var docEl = document.getElementById("image-source"); // ONLY image as fullScreen
308 var requestFullScreen =
309 docEl.requestFullscreen ||
310 docEl.mozRequestFullScreen ||
311 docEl.webkitRequestFullScreen ||
312 docEl.msRequestFullscreen;
313 var cancelFullScreen =
314 doc.exitFullscreen ||
315 doc.mozCancelFullScreen ||
316 doc.webkitExitFullscreen ||
317 doc.msExitFullscreen;
318 if (
319 !doc.fullscreenElement &&
320 !doc.mozFullScreenElement &&
321 !doc.webkitFullscreenElement &&
322 !doc.msFullscreenElement
323 ) {
324 if (requestFullScreen === undefined) {
325 alert("Failed to render {{ media_title }} in fullScreen");
326 }
327 requestFullScreen.call(docEl);
328 } else {
329 if (cancelFullScreen === undefined) {
330 alert("Failed to cacnel fullScreen for {{ media_title }}");
331 }
332 cancelFullScreen.call(doc);
333 }
334 }
335 {% if previous %}
336 // Add event listener for the left arrow key
337 document.addEventListener('keydown', navigateLeft);
338 function navigateLeft(event) {
339 if (event.key === 'ArrowLeft') {
340 // Navigate to the previous image
341 window.location='{{ previous }}';
342 }
343 }
344 {% endif %}
345 {% if next %}
346 // Add event listener for the right arrow key
347 document.addEventListener('keydown', navigateRight);
348 function navigateRight(event) {
349 if (event.key === 'ArrowRight') {
350 // Navigate to the next image
351 window.location='{{ next }}';
352 }
353 }
354 {% endif %}
355 </script>
356</body>
357</html>
358"###.to_string()
359}