Browse Source

Updated part of the homepage to tocas

Toby Chui 1 day ago
parent
commit
eec55fbf75

+ 70 - 71
firmware/v4/web-server/router.ino

@@ -9,87 +9,86 @@
     By default, all route will go to the SD card /www/ folder
 */
 class MainRouter : public AsyncWebHandler {
-  public:
-    MainRouter() {}
-    virtual ~MainRouter() {}
+public:
+  MainRouter() {}
+  virtual ~MainRouter() {}
 
-    bool canHandle(AsyncWebServerRequest *request) {
-      String requestURI = request->url().c_str();
-      if (requestURI.equals("/upload")) {
-        //File Upload Endpoint
-        return false;
-      } else if (requestURI.startsWith("/api/")) {
-        //API paths
-        return false;
-      }else if (requestURI.startsWith("/share/")) {
-        //Share paths
-        return false;
-      }
-      return true;
-    }
-
-    //Main Routing Logic Here
-    void handleRequest(AsyncWebServerRequest *request) {
-      String requestURI = request->url().c_str();
+  bool canHandle(AsyncWebServerRequest *request) {
+    String requestURI = request->url().c_str();
+    if (requestURI.equals("/upload")) {
+      //File Upload Endpoint
+      return false;
+    } else if (requestURI.startsWith("/api/")) {
+      //API paths
+      return false;
+    } else if (requestURI.startsWith("/share/")) {
+      //Share paths
+      return false;
+    } 
+    return true;
+  }
 
-      /* Rewrite the request path if URI contains ./ */
-      if (requestURI.indexOf("./") > 0) {
-        requestURI.replace("./", "");
-        AsyncWebServerResponse *response = request->beginResponse(307);
-        response->addHeader("Cache-Control", "no-cache");
-        response->addHeader("Location", requestURI);
-        request->send(response);
-        return;
-      }
-      
-      /* Special Routing Rules */
-      //Redirect / back to index.html
-      if (requestURI == "/") {
-        request->redirect("/index.html");
-        return;
-      }
+  //Main Routing Logic Here
+  void handleRequest(AsyncWebServerRequest *request) {
+    String requestURI = request->url().c_str();
 
-      //Special interfaces that require access controls
-      if (requestURI.startsWith("/store/")) {
-        //Private file storage. Not allow access
-        AsyncWebServerResponse *response = request->beginResponse(401, "text/html", "403 - Forbidden");
-        request->send(response);
-        return;
-      }
+    /* Rewrite the request path if URI contains ./ */
+    if (requestURI.indexOf("./") > 0) {
+      requestURI.replace("./", "");
+      AsyncWebServerResponse *response = request->beginResponse(307);
+      response->addHeader("Cache-Control", "no-cache");
+      response->addHeader("Location", requestURI);
+      request->send(response);
+      return;
+    }
 
-      /* Default Routing Rules */
+    /* Special Routing Rules */
+    //Redirect / back to index.html
+    if (requestURI == "/") {
+      request->redirect("/index.html");
+      return;
+    }
 
-      Serial.println("URI: " + requestURI + " | MIME: " + getMime(requestURI));
-      //Check if the file exists on the SD card
-      if (SD.exists("/www" + requestURI)) {
-        // File exists on SD card web root
-        if (IsDir("/www" + requestURI)) {
-          //Requesting a directory
-          if (!requestURI.endsWith("/")) {
-            //Missing tailing slash
-            request->redirect(requestURI + "/");
-            return;
-          }
+    //Special interfaces that require access controls
+    if (requestURI.startsWith("/store/")) {
+      //Private file storage. Not allow access
+      AsyncWebServerResponse *response = request->beginResponse(401, "text/html", "403 - Forbidden");
+      request->send(response);
+      return;
+    }
 
-          if (SD.exists("/www" + requestURI + "index.html")) {
-            request->send(SDFS, "/www" + requestURI + "/index.html", "text/html", false);
-          } else {
-            HandleDirRender(request, requestURI , "/www" + requestURI);
-          }
+    /* Default Routing Rules */
+    Serial.println("URI: " + requestURI + " | MIME: " + getMime(requestURI));
+    //Check if the file exists on the SD card
+    if (SD.exists("/www" + requestURI)) {
+      // File exists on SD card web root
+      if (IsDir("/www" + requestURI)) {
+        //Requesting a directory
+        if (!requestURI.endsWith("/")) {
+          //Missing tailing slash
+          request->redirect(requestURI + "/");
+          return;
+        }
 
+        if (SD.exists("/www" + requestURI + "index.html")) {
+          request->send(SDFS, "/www" + requestURI + "/index.html", "text/html", false);
         } else {
-          request->send(SDFS, "/www" + requestURI, getMime(requestURI), false);
+          HandleDirRender(request, requestURI, "/www" + requestURI);
         }
+
       } else {
-        // File does not exist in web root
-        AsyncResponseStream *response = request->beginResponseStream("text/html");
-        Serial.println("NOT FOUND: " + requestURI);
-        prettyPrintRequest(request);
-        response->print("<!DOCTYPE html><html><head><title>Not Found</title></head><body>");
-        response->print("<p>404 - Not Found</p>");
-        response->printf("<p>Requesting http://%s with URI: %s</p>", request->host().c_str(), request->url().c_str());
-        response->print("</body></html>");
-        request->send(response);
+        request->send(SDFS, "/www" + requestURI, getMime(requestURI), false);
       }
+    } else {
+      // File does not exist in web root
+      AsyncResponseStream *response = request->beginResponseStream("text/html");
+      Serial.println("NOT FOUND: " + requestURI);
+      prettyPrintRequest(request);
+      response->print("<!DOCTYPE html><html><head><title>Not Found</title></head><body>");
+      response->print("<p>404 - Not Found</p>");
+      response->printf("<p>Requesting http://%s with URI: %s</p>", request->host().c_str(), request->url().c_str());
+      response->print("</body></html>");
+      request->send(response);
     }
+  }
 };

+ 1 - 2
firmware/v4/web-server/server.ino

@@ -150,8 +150,7 @@ void initWebServer() {
   server.on("/api/share/list", HTTP_GET, HandleShareList);
   server.on("/api/share/clean", HTTP_GET, HandleShareListCleaning);
   server.on("/share", HTTP_GET, HandleShareAccess);
-  
-  
+
   /* Preference */
   server.on("/api/pref/set", HTTP_GET, HandleSetPref);
   server.on("/api/pref/get", HTTP_GET, HandleLoadPref);

+ 60 - 100
sd_card/www/about.html

@@ -1,103 +1,63 @@
-<!DOCTYPE html>
-<html>
-<head>
-	
-  <!-- HTML Meta Tags -->
-  <title>About WebStick</title>
-  <meta name="description" content="A tiny web server powered by ESP8266, designed by tobychui">
-  <meta name="viewport" content="width=device-width, initial-scale=1" >
-  
-  <!-- Facebook Meta Tags -->
-  <meta property="og:url" content="https://imuslab.com">
-  <meta property="og:type" content="website">
-  <meta property="og:title" content="Welcome to WebStick!">
-  <meta property="og:description" content="A tiny web server powered by ESP8266, designed by tobychui">
-  <meta property="og:image" content=" ">
 
-  <!-- Twitter Meta Tags -->
-  <meta name="twitter:card" content="summary_large_image">
-  <meta property="twitter:domain" content="imuslab.com">
-  <meta property="twitter:url" content="https://imuslab.com">
-  <meta name="twitter:title" content="Welcome to WebStick!">
-  <meta name="twitter:description" content="A tiny web server powered by ESP8266, designed by tobychui">
-  <meta name="twitter:image" content=" ">
+<div class="ts-container is-very-narrow">
+  <div class="ts-image is-rounded">
+      <img src="img/wallpaper.jpg" width="100%">
+  </div>
+  <div class="ts-header has-top-spaced-large">What is a WebStick?</div>
+  <span class="ts-text">WebStick is a USB stick form factor web server powered by a ESP12E/F module. 
+      The web content is serve over the SD card connected to the MCU via SPI link, 
+      providing basic HTTP web server function with less than 2W of power usage.</span>
+  <div class="ts-divider has-top-spaced-large has-bottom-spaced-large"></div>
 
-  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" />
-  <script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
+  <div class="ts-header">Why WebStick?</div>
 
-  <style>
-	.imgwrapper{
-        max-height: 200px;
-        overflow: hidden;
-    }
-  </style>
-</head>
-<body>
-	<div class="navibar"></div>
-    <div class="imgwrapper">
-        <img src="img/wallpaper.jpg" class="ui fluid image">
-    </div>
-    <div class="ui container">
-        <br>
-        <h3>What is a WebStick?</h3>
-        <p>WebStick is a USB stick form factor web server powered by a ESP12E/F module. 
-            The web content is serve over the SD card connected to the MCU via SPI link, 
-            providing basic HTTP web server function with less than 2W of power usage.</p>
-        <h3>Why WebStick?</h3>
-        <p>If you are just hosting a web server for personal use with a few occasional guests, 
-            you do not need a Raspberry Pi that draws 15W 24/7 just for this purpose. <br>
-            Instead, a WebStick with ESP8266 is just enough to do the tasks. 
-            With the help of CDN and Caching, even a 2W MCU running over WiFi 
-            can provide relatively acceptable performance for basic HTTP web services.</p>
-        <h3>Specification</h3>
-        <table class="ui very basic celled collapsing table">
-            <thead>
-              <tr><th>Item</th>
-              <th>Properties</th>
-            </tr></thead>
-            <tbody>
-              <tr>
-                <td data-label="">Power Requirement</td>
-                <td data-label="">5V 1A</td>
-              </tr>
-              <tr>
-                <td data-label="">Actual Power Draw</td>
-                <td data-label="">around 2 - 3W</td>
-              </tr>
-              <tr>
-                <td data-label="">Wireless Network Speed</td>
-                <td data-label="">2 - 4 Mbps</td>
-              </tr>
-              <tr>
-                <td data-label="">Max SD card size supported</td>
-                <td data-label="">4GB</td>
-              </tr>
-              <tr>
-                <td data-label="">SD card format</td>
-                <td data-label="">FAT32</td>
-              </tr>
-              <tr>
-                <td data-label="">Arduino IDE Programmable</td>
-                <td data-label=""><i class="ui green check icon"></i></td>
-              </tr>
-              <tr>
-                <td data-label="">Run PHP / nodejs</td>
-                <td data-label=""><i class="ui red times icon"></i></td>
-              </tr>
-              <tr>
-                <td data-label="">Recommended Number of Users</td>
-                <td data-label="">less than 20 viewers per day</td>
-              </tr>
-            </tbody>
-          </table>
-        <a class="ui basic button" href="index.html">Back</a>
-		<br><br>
-		<p>This site is hosted on a WebStick designed by <a href="https://imuslab.com">imuslab</a></p>
-        <br><br>
-	</div>
-    <script>
-        $(".navibar").load("navi.html");
-    </script>
-</body>
-</html>
+  <span class="ts-text">If you are just hosting a web server for personal use with a few occasional guests, 
+      you do not need a Raspberry Pi that draws 15W 24/7 just for this purpose.</span>
+
+  <span class="ts-text">Instead, a WebStick with ESP8266 is just enough to do the tasks. 
+      With the help of CDN and Caching, even a 2W MCU running over WiFi 
+      can provide relatively acceptable performance for basic HTTP web services.</span>
+  <div class="ts-divider has-top-spaced-large has-bottom-spaced-large"></div>
+      
+  <div class="ts-header">Specification</div>
+  <table class="ts-table is-single-line has-top-spaced-small">
+      <thead>
+        <tr><th>Item</th>
+        <th>Properties</th>
+      </tr></thead>
+      <tbody>
+        <tr>
+          <td data-label="">Power Requirement</td>
+          <td data-label="">5V 1A</td>
+        </tr>
+        <tr>
+          <td data-label="">Actual Power Draw</td>
+          <td data-label="">around 2 - 3W</td>
+        </tr>
+        <tr>
+          <td data-label="">Wireless Network Speed</td>
+          <td data-label="">2 - 4 Mbps</td>
+        </tr>
+        <tr>
+          <td data-label="">Max SD card size</td>
+          <td data-label="">4GB</td>
+        </tr>
+        <tr>
+          <td data-label="">SD card format</td>
+          <td data-label="">FAT32</td>
+        </tr>
+        <tr>
+          <td data-label="">Arduino IDE Support</td>
+          <td data-label=""><span class="ts-icon is-check-icon" style="color:var(--ts-positive-400);"></span></td>
+        </tr>
+        <tr>
+          <td data-label="">Run PHP / nodejs</td>
+          <td data-label=""><span class="ts-icon is-xmark-icon" style="color:var(--ts-negative-400);"></span></td>
+        </tr>
+        <tr>
+          <td data-label="">Max No. of Users</td>
+          <td data-label="">~20 viewers per day</td>
+        </tr>
+      </tbody>
+    </table>
+</div>

+ 4 - 0
sd_card/www/admin/fs.html

@@ -27,6 +27,10 @@
                 user-select: none;
                 pointer-events: none;
             }
+
+            #propertiesView{
+                overflow-x: hidden;
+            }
         </style>
     </head>
     <body class="whiteTheme">

BIN
sd_card/www/img/logo.png


BIN
sd_card/www/img/wallpaper.jpg


+ 64 - 88
sd_card/www/index.html

@@ -1,98 +1,73 @@
 <!DOCTYPE html>
 <html>
 <head>
-	
-  <!-- HTML Meta Tags -->
-  <title>Welcome to WebStick!</title>
-  <meta name="description" content="A tiny web server powered by ESP8266, designed by tobychui">
-  <meta name="viewport" content="width=device-width, initial-scale=1" >
-  
-  <!-- Facebook Meta Tags -->
-  <meta property="og:url" content="https://imuslab.com">
-  <meta property="og:type" content="website">
-  <meta property="og:title" content="Welcome to WebStick!">
-  <meta property="og:description" content="A tiny web server powered by ESP8266, designed by tobychui">
-  <meta property="og:image" content=" ">
-
-  <!-- Twitter Meta Tags -->
-  <meta name="twitter:card" content="summary_large_image">
-  <meta property="twitter:domain" content="imuslab.com">
-  <meta property="twitter:url" content="https://imuslab.com">
-  <meta name="twitter:title" content="Welcome to WebStick!">
-  <meta name="twitter:description" content="A tiny web server powered by ESP8266, designed by tobychui">
-  <meta name="twitter:image" content=" ">
-
-  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" />
-  <script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
-
-  <style>
-	.character.ring{
-		width: 320px;
-		height: 320px;
-		margin-top: 20px;
-		border: 5px solid #f9c729 !important;
-		background-color: white;
-		border-radius: 50%;
-		display: inline-block;
-	}
-	
-	.character.infill{
-		width: 260px;
-		height: 260px;
-		margin-top: 25px;
-		background-color: #ffcb2e;
-		border-radius: 50%;
-		display: inline-block;
-	}
-
-	.charactercard{
-		width: 375px !important;
-		border: 0px solid transparent;
-		-webkit-box-shadow: none !important;
-		box-shadow: -3px 12px 19px 5px rgba(204,204,204,0.59) !important;
-	}
-
-	.dark.divider{
-		height: 3px;
-		background: #020202;
-		width: 60px;
-		margin-bottom: 1.4em;
-		margin-top: 1.6em;
-	}
-
-	.breadcrumb .section{
-		font-weight: 300;
-		font-size: 1.2em;
-	}
-
-	.blacklink{
-		color: #020202;
-		transition: margin-top ease-in-out 0.1s, color ease-in-out 0.1s !important;
-	}
-
-	.blacklink:hover{
-		color: #020202;
-		opacity: 0.7;
-		margin-top: -1.2em !important;
-	}
-	
-	.linkbuttons{
-		padding: 2em;
-	}
+	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+	<!-- HTML Meta Tags -->
+	<title>Homepage | WebStick</title>
+	<meta name="description" content="A tiny web server powered by ESP8266, designed by tobychui">
+	<meta name="viewport" content="width=device-width, initial-scale=1" >
+		
+	<!-- Facebook Meta Tags -->
+	<meta property="og:url" content="https://imuslab.com">
+	<meta property="og:type" content="website">
+	<meta property="og:title" content="Welcome to WebStick!">
+	<meta property="og:description" content="A tiny web server powered by ESP8266, designed by tobychui">
+	<meta property="og:image" content=" ">
 
-	.linkbuttons .ui.white.button{
-		background: white !important;
-		padding: 1.2em;
-		margin-top: 0.8em;
-	}
+	<!-- Twitter Meta Tags -->
+	<meta name="twitter:card" content="summary_large_image">
+	<meta property="twitter:domain" content="imuslab.com">
+	<meta property="twitter:url" content="https://imuslab.com">
+	<meta name="twitter:title" content="Welcome to WebStick!">
+	<meta name="twitter:description" content="A tiny web server powered by ESP8266, designed by tobychui">
+	<meta name="twitter:image" content=" ">
 
-	.linkbuttons .ui.white.button:hover{
-		opacity: 0.8;
-	}
-  </style>
+  	<!-- CDN -->
+	<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocas-ui/5.0.2/tocas.min.css">
+	<script src="https://cdnjs.cloudflare.com/ajax/libs/tocas-ui/5.0.2/tocas.min.js"></script>
+	<link rel="preconnect" href="https://fonts.googleapis.com">
+	<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+	<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500;700&display=swap" rel="stylesheet">
 </head>
 <body>
+	<div class="ts-content">
+		<div class="ts-tab is-segmented">
+			<a class="item is-active" data-tab="home">Home</a>
+			<a class="item" data-tab="about">About</a>
+			<a class="item" data-tab="posts">Posts</a>
+			<a class="item" data-tab="downloads">Downloads</a>
+			<a class="item" data-tab="qr">QR</a>
+		</div>
+		<div class="has-top-spaced-small"></div>
+		<div class="ts-content" id="home">
+			<p>Welcome to the Home tab!</p>
+		</div>
+		<div class="ts-content" id="about">
+			
+		</div>
+		<div class="ts-content" id="posts">
+			<p>Check out the latest posts in the Posts tab.</p>
+		</div>
+		<div class="ts-content" id="downloads">
+			<p>Find useful resources in the Downloads tab.</p>
+		</div>
+		<div class="ts-content" id="qr">
+			<p>Generate QR codes in the QR tab.</p>
+		</div>
+		
+		<div class="ts-divider"></div>
+		<div class="ts-content">
+			<p class="ts-text">This site is hosted on a WebStick designed by <a href="https://imuslab.com" target="_blank">tobychui</a></p>
+		</div>
+	</div>
+	
+	<script>
+		$("#about").load("about.html");
+		$("#qr").html('<iframe src="tool/qr.html" style="border: none; width: 100%; height: calc(100vh - 200px);"></iframe>');
+	</script>
+	
+	<!-- 
 	<div class="ui container" align="center">
 	<br>
 		<div class="ui fluid card charactercard">
@@ -130,5 +105,6 @@
 		<p>This site is hosted on a WebStick designed by <a href="https://imuslab.com">imuslab</a></p>
 		<br>
 	</div>
+-->
 </body>
 </html>

+ 59 - 56
sd_card/www/login.html

@@ -1,67 +1,70 @@
 <!DOCTYPE html>
 <html>
-<head>
-  <title>Login</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1" >
+  <head>
+    <title>Login</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1" >
+    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocas-ui/5.0.2/tocas.min.css">
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/tocas-ui/5.0.2/tocas.min.js"></script>
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500;700&display=swap" rel="stylesheet">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+  </head>
+  <body>
+    <div class="ts-app-center">
+      <div class="content">
+          <a href="index.html">
+            <div class="ts-image is-centered">
+              <img src="img/logo.png" width="150">
+            </div>
+          </a>
+          <div class="has-top-spaced-large"></div>
+          <div class="ts-box has-top-spaced-large" style="width: 260px">
+              <div class="ts-content">
+                  <div class="ts-wrap is-vertical">
+                      <div class="ts-text is-label">Username</div>
+                      <div class="ts-input is-start-icon is-underlined">
+                          <span class="ts-icon is-user-icon"></span>
+                          <input type="text" name="username" placeholder="Username" required>
+                      </div>
+                      <div class="ts-text is-label">Password</div>
+                      <div class="ts-input is-start-icon is-underlined">
+                          <span class="ts-icon is-lock-icon"></span>
+                          <input type="password" name="password" placeholder="Password" required>
+                      </div>
+                      <button class="ts-button is-fluid" onclick="login(event);">Login</button>
+                  </div>
 
-  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" />
-  <script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.js"></script>
-
-  <style>
-    .imgwrapper{
-        max-height: 200px;
-        overflow: hidden;
-    }
-  </style>
-</head>
-<body>
-	<div class="navibar"></div>
-    <div class="imgwrapper">
-        <img src="img/wallpaper.jpg" class="ui fluid image">
-    </div>
-    <div class="ui container">
-        <br><br>
-        <div class="ui very padded text container segment">
-            <h2 class="ui header">Admin Panel</h2>
-            <form id="loginForm" class="ui form">
-              <div class="field">
-                <label>Username</label>
-                <input type="text" name="username" placeholder="Username">
-              </div>
-              <div class="field">
-                <label>Password</label>
-                <input type="password" name="password" placeholder="Password">
+                  <a class="ts-text is-icon-link has-top-spaced-large" href="index.html">
+                    <span class="ts-icon is-arrow-left-icon"></span>
+                    Back
+                </a>
               </div>
-              <button id="loginButton" class="ui basic button" type="submit"><i class="ui blue sign-in icon"></i> Login</button>
-            </form>
           </div>
-	</div>
-    <script>
-        $(".navibar").load("navi.html");
-
-
-        $('#loginForm').submit(function(e) {
-            e.preventDefault(); // Prevent form submission
+      </div>
+    </div>
 
-            // Get the input values
-            var username = $('input[name="username"]').val();
-            var password = $('input[name="password"]').val();
+    <script>
+      function login(e){
+        e.preventDefault(); // Prevent form submission
+        // Get the input values
+        var username = $('input[name="username"]').val();
+        var password = $('input[name="password"]').val();
 
-            $.ajax({
-                url: "/api/auth/login?username=" + username + "&password=" + password,
-                method: "POST",
-                success: function(data){
-                    if (data.error != undefined){
-                        alert(data.error);
-                    }else{
-                        //Logged in
-                        window.location.href = "/admin/";
-                    }
+        $.ajax({
+            url: "/api/auth/login?username=" + username + "&password=" + password,
+            method: "POST",
+            success: function(data){
+                if (data.error != undefined){
+                  $('input[name="username"], input[name="password"]').addClass('is-negative');
+                }else{
+                    //Logged in
+                    window.location.href = "/admin/";
                 }
-            })
+            }
         });
-
+      }
     </script>
-</body>
+  </body>
 </html>

+ 0 - 7
sd_card/www/navi.html

@@ -1,7 +0,0 @@
-<div class="ui container">
-    <br>
-    <a href="index.html" style="user-select: none; height: 45px;">
-        <img class="ui small image" src="img/logo.png">
-    </a>
-    <br>
-</div>

+ 24 - 49
sd_card/www/tool/qr.html

@@ -5,39 +5,16 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>QR Code Generator</title>
 	<link rel="icon" type="image/png" href="/favicon.png" />
+	<!-- QR Code -->
     <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
 	<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
-	<script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.3/semantic.min.js" integrity="sha512-gnoBksrDbaMnlE0rhhkcx3iwzvgBGz6mOEj4/Y5ZY09n55dYddx6+WYc72A55qEesV8VX2iMomteIwobeGK1BQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
-	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.3/semantic.min.css" integrity="sha512-3quBdRGJyLy79hzhDDcBzANW+mVqPctrGCfIPosHQtMKb3rKsCxfyslzwlz2wj1dT8A7UX+sEvDjaUv+WExQrA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
-	 <link rel="preconnect" href="https://fonts.googleapis.com">
+	<!-- css -->
+	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocas-ui/5.0.2/tocas.min.css">
+	<script src="https://cdnjs.cloudflare.com/ajax/libs/tocas-ui/5.0.2/tocas.min.js"></script>
+	<link rel="preconnect" href="https://fonts.googleapis.com">
 	<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-	<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@100;200&display=swap" rel="stylesheet">
-
+	<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@400;500;700&display=swap" rel="stylesheet">
     <style>
-		body {
-            
-        }
-
-		.main{
-			display: flex;
-            align-items: center;
-            justify-content: center;
-            height: calc(100vh - 60px);
-            margin: 0;
-		}
-		
-        #qr-code {
-            max-width: 300px;
-			height: 300px;
-        }
-
-        #generate-btn {
-            cursor: pointer;
-        }
-		
-		.ui.header,button,input{
-		    font-family: 'Noto Sans TC', sans-serif !important;
-		}
 		
 		@media screen and (min-width: 768px) {
 			#title{
@@ -54,31 +31,29 @@
 				padding-left: 5em;
 			}
 		}
+
+		#qr-code {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin: 0 auto;
+			height: 300px; /* Match the QR code height */
+			width: 300px; /* Match the QR code width */
+		}
     </style>
 </head>
 <body>
-	<div class="main">
-		<div class="ui stackable grid">
-		<div id="title" class="eight wide column" align="center">
-			<h2 class="ui header">
-			QR Code Generator
-			<div class="sub header">No ads and it just works</div>
-			</h2>
-			<br>
-			<a href="../">Back to homepage</a>
-		</div>
-		<div id="qrgrid" class="eight wide column"  align="center">
-		<div style="width: 300px">
-			<div class="ui fluid input" style="margin-bottom: 1em;">
-			<input type="text" id="text-input" placeholder="Enter text for QR code" onkeypress="handleKeyPress(event)">
-			</div>
-			<button class="ui fluid basic button" id="generate-btn" onclick="generateQRCode()">Generate QR Code</button>
-			<div class="ui divider"></div>
-			<div id="qr-code"></div>
+	<div class="ts-app-center">
+		<div class="ts-content">
+			<div >
+				<div class="ts-input is-circular" style="margin-bottom: 1em;">
+					<input type="text" id="text-input" placeholder="Enter text for QR code" onkeypress="handleKeyPress(event)">
+				</div>
+				<button class="ts-button is-fluid" id="generate-btn" onclick="generateQRCode()">Generate QR Code</button>
+				<div class="ts-divider has-top-spaced-large has-bottom-spaced-large"></div>
+				<div id="qr-code"></div>
 			</div>
 		</div>
-		</div>
-		
 	</div>
     <script>
 		function initQrCode(){