- // ==UserScript==
- // @name macOS-like Custom Start Page Full Version
- // @namespace http://tampermonkey.net/
- // @version 2.1
- // @description A full version macOS-like start page with weather, to-do persistence, voice search, and responsive design
- // @author 文熙
- // @license MIT
- // @match *://*/blank.html
- // @grant none
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- // Helper function to detect if it's mobile
- function isMobile() {
- return /Mobi|Android/i.test(navigator.userAgent);
- }
-
- // Define custom HTML for macOS-style start page with advanced features
- const startPageHtml = `
- <div class="container">
- <div class="widget glass">
- <h1 class="title">Good Day</h1>
- <div class="time-widget" id="currentTime">--:--:--</div>
- <div class="search-section">
- <input type="text" id="searchBar" class="search-bar" placeholder="Search the web..." />
- <button id="voiceSearch" class="voice-search" title="Voice Search"><img src="https://upload.wikimedia.org/wikipedia/commons/e/e1/Microphone_Icon.svg" alt="Voice Search" width="24" height="24"></button>
- </div>
- <select id="searchEngine" class="search-engine">
- <option value="https://www.google.com/search?q=">Google</option>
- <option value="https://www.bing.com/search?q=">Bing</option>
- <option value="https://duckduckgo.com/?q=">DuckDuckGo</option>
- </select>
- </div>
- <div class="dock">
- <a href="https://www.google.com" target="_blank" class="dock-icon"><img src="https://upload.wikimedia.org/wikipedia/commons/2/2f/Google_2015_logo.svg" alt="Google" width="48" height="48"></a>
- <a href="https://www.github.com" target="_blank" class="dock-icon"><img src="https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg" alt="GitHub" width="48" height="48"></a>
- <a href="https://www.reddit.com" target="_blank" class="dock-icon"><img src="https://upload.wikimedia.org/wikipedia/en/8/82/Reddit_logo_and_wordmark.svg" alt="Reddit" width="48" height="48"></a>
- </div>
- <div class="widgets-container">
- <div class="calendar-widget glass">
- <div id="currentDate">--/--/----</div>
- </div>
- <div class="weather-widget glass">
- <h2 class="weather-title">Weather</h2>
- <div id="weatherInfo">Loading...</div>
- </div>
- <div class="todo-widget glass">
- <h2 class="todo-title">To-Do List</h2>
- <ul id="todoList" class="todo-list"></ul>
- <input type="text" id="todoInput" class="todo-input" placeholder="Add a new task..." />
- <button id="clearTodos" class="clear-button">Clear All</button>
- </div>
- </div>
- <div class="settings glass">
- <button id="themeButton" class="theme-button">Change Theme</button>
- </div>
- </div>
- `;
-
- // Inject the HTML into the body
- document.body.innerHTML = startPageHtml;
- document.title = "macOS-like Start Page";
-
- // Function to update the current time every second
- function updateTime() {
- const now = new Date();
- const hours = String(now.getHours()).padStart(2, '0');
- const minutes = String(now.getMinutes()).padStart(2, '0');
- const seconds = String(now.getSeconds()).padStart(2, '0');
- document.getElementById('currentTime').textContent = `${hours}:${minutes}:${seconds}`;
- }
- setInterval(updateTime, 1000);
- updateTime();
-
- // Function to update the current date
- function updateDate() {
- const now = new Date();
- const day = String(now.getDate()).padStart(2, '0');
- const month = String(now.getMonth() + 1).padStart(2, '0');
- const year = now.getFullYear();
- document.getElementById('currentDate').textContent = `${day}/${month}/${year}`;
- }
- updateDate();
-
- // Search bar functionality with engine selection
- const searchBar = document.getElementById('searchBar');
- const searchEngine = document.getElementById('searchEngine');
- searchBar.addEventListener('keypress', function(e) {
- if (e.key === 'Enter') {
- const query = searchBar.value.trim();
- if (query) {
- const engineUrl = searchEngine.value;
- window.location.href = `${engineUrl}${encodeURIComponent(query)}`;
- }
- }
- });
-
- // Voice Search functionality
- const voiceSearchButton = document.getElementById('voiceSearch');
- voiceSearchButton.addEventListener('click', function() {
- const recognition = new webkitSpeechRecognition();
- recognition.lang = 'en-US';
- recognition.start();
- recognition.onresult = function(event) {
- const query = event.results[0][0].transcript;
- searchBar.value = query;
- const engineUrl = searchEngine.value;
- window.location.href = `${engineUrl}${encodeURIComponent(query)}`;
- };
- });
-
- // To-Do List functionality with persistence
- const todoInput = document.getElementById('todoInput');
- const todoList = document.getElementById('todoList');
- const clearTodosButton = document.getElementById('clearTodos');
-
- // Load saved tasks from localStorage
- const savedTodos = JSON.parse(localStorage.getItem('todos')) || [];
- savedTodos.forEach(task => {
- const listItem = createTodoItem(task);
- todoList.appendChild(listItem);
- });
-
- todoInput.addEventListener('keypress', function(e) {
- if (e.key === 'Enter') {
- const task = todoInput.value.trim();
- if (task) {
- const listItem = createTodoItem(task);
- todoList.appendChild(listItem);
- saveTodoItem(task);
- todoInput.value = ''; // Clear input after adding task
- }
- }
- });
-
- clearTodosButton.addEventListener('click', function() {
- todoList.innerHTML = '';
- localStorage.removeItem('todos');
- });
-
- function createTodoItem(task) {
- const listItem = document.createElement('li');
- listItem.textContent = task;
- listItem.addEventListener('click', () => {
- listItem.remove();
- removeTodoItem(task);
- });
- return listItem;
- }
-
- function saveTodoItem(task) {
- const todos = JSON.parse(localStorage.getItem('todos')) || [];
- todos.push(task);
- localStorage.setItem('todos', JSON.stringify(todos));
- }
-
- function removeTodoItem(task) {
- const todos = JSON.parse(localStorage.getItem('todos')) || [];
- const updatedTodos = todos.filter(t => t !== task);
- localStorage.setItem('todos', JSON.stringify(updatedTodos));
- }
-
- // Weather Widget
- async function fetchWeather() {
- if (navigator.geolocation) {
- navigator.geolocation.getCurrentPosition(async function(position) {
- const lat = position.coords.latitude;
- const lon = position.coords.longitude;
- const apiKey = 'YOUR_OPENWEATHER_API_KEY'; // Replace with your API key
- const weatherUrl = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&units=metric&appid=${apiKey}`;
- const response = await fetch(weatherUrl);
- const data = await response.json();
- const weatherInfo = `${data.weather[0].description}, ${data.main.temp}°C`;
- document.getElementById('weatherInfo').textContent = weatherInfo;
- });
- } else {
- document.getElementById('weatherInfo').textContent = 'Geolocation not supported';
- }
- }
- fetchWeather();
-
- // Theme toggle button
- const themeButton = document.getElementById('themeButton');
- const currentTheme = localStorage.getItem('theme') || 'light';
- document.body.classList.toggle('dark-theme', currentTheme === 'dark');
- themeButton.textContent = currentTheme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode';
-
- themeButton.addEventListener('click', () => {
- const isDark = document.body.classList.toggle('dark-theme');
- localStorage.setItem('theme', isDark ? 'dark' : 'light');
- themeButton.textContent = isDark ? 'Switch to Light Mode' : 'Switch to Dark Mode';
- });
-
- // Additional custom styles
- const customCss = `
- body {
- margin: 0;
- padding: 0;
- background: linear-gradient(135deg, #f0f0f5, #d0d0e5);
- font-family: -apple-system, BlinkMacSystemFont, "San Francisco", "Helvetica Neue", sans-serif;
- display: flex;
- justify-content: center;
- align-items: center;
- height: 100vh;
- transition: background-color 0.5s;
- }
- body.dark-theme {
- background-color: #2c2c2c;
- color: #ffffff;
- }
- .container {
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 90%;
- max-width: 1200px;
- }
- .widget, .glass {
- text-align: center;
- background: rgba(255, 255, 255, 0.25);
- backdrop-filter: blur(10px);
- padding: 2rem;
- border-radius: 20px;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
- margin-bottom: 2rem;
- width: 100%;
- }
- .title {
- font-size: 2.5rem;
- color: #333;
- margin-bottom: 1rem;
- }
- .time-widget {
- font-size: 2rem;
- color: #555;
- margin-bottom: 1rem;
- }
- .search-bar {
- width: 80%;
- padding: 0.75rem;
- font-size: 1.2rem;
- border: none;
- border-radius: 20px;
- outline: none;
- text-align: center;
- background-color: rgba(255, 255, 255, 0.7);
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
- transition: background-color 0.3s ease, box-shadow 0.3s ease;
- margin-bottom: 1rem;
- }
- .search-bar:focus {
- background-color: rgba(255, 255, 255, 0.9);
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
- }
- .voice-search {
- font-size: 1.5rem;
- background-color: #007aff;
- color: #fff;
- border: none;
- border-radius: 50%;
- padding: 0.5rem;
- cursor: pointer;
- margin-bottom: 1rem;
- }
- .search-engine {
- padding: 0.5rem;
- border: none;
- border-radius: 10px;
- margin-bottom: 2rem;
- }
- .dock {
- display: flex;
- justify-content: center;
- gap: 2rem;
- }
- .dock-icon {
- font-size: 1.2rem;
- color: #fff;
- background-color: rgba(0, 0, 0, 0.6);
- padding: 0.75rem 1.5rem;
- border-radius: 15px;
- text-decoration: none;
- transition: background-color 0.3s ease, transform 0.3s ease;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
- }
- .dock-icon:hover {
- background-color: rgba(0, 0, 0, 0.8);
- transform: translateY(-5px);
- }
- .widgets-container {
- display: flex;
- flex-direction: column;
- justify-content: space-around;
- gap: 2rem;
- width: 100%;
- }
- .calendar-widget, .weather-widget, .todo-widget {
- padding: 1.5rem;
- background: rgba(255, 255, 255, 0.3);
- border-radius: 15px;
- backdrop-filter: blur(10px);
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
- }
- .calendar-widget #currentDate {
- font-size: 1.5rem;
- color: #333;
- }
- .weather-title, .todo-title {
- font-size: 1.5rem;
- color: #333;
- margin-bottom: 1rem;
- }
- .todo-list {
- list-style: none;
- padding: 0;
- }
- .todo-list li {
- background-color: rgba(0, 0, 0, 0.05);
- padding: 0.5rem 1rem;
- border-radius: 10px;
- margin-bottom: 0.5rem;
- cursor: pointer;
- }
- .todo-list li:hover {
- background-color: rgba(0, 0, 0, 0.1);
- }
- .theme-button {
- padding: 0.75rem 1.5rem;
- background-color: #007aff;
- color: #fff;
- border: none;
- border-radius: 10px;
- cursor: pointer;
- }
- `;
-
- // Inject the custom CSS into the page
- const styleSheet = document.createElement("style");
- styleSheet.type = "text/css";
- styleSheet.innerText = customCss;
- document.head.appendChild(styleSheet);
-
- })();