OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
21
public/assets/js/libs/pomodoro/LICENSE
Normal file
21
public/assets/js/libs/pomodoro/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Andy Roche
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
10
public/assets/js/libs/pomodoro/README.md
Normal file
10
public/assets/js/libs/pomodoro/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# pomodoro
|
||||
#### A simple pomodoro timer written in JavaScript. Find it at http://roche.io/pomodoro/
|
||||
|
||||
There are plenty of timers like this online ([Moosti](http://moosti.com/), [Tomato Timer](http://tomato-timer.com/)), but the best workflow tool is the one you use. This was a quick side project for me in September 2015 to brush up on my web development and build something I would use myself. It takes the best features from all of the similar timers, and drops the cruft.
|
||||
|
||||
#### Features:
|
||||
- Minutes remaining shown in browser tab
|
||||
- Favicon change and alarm on timer complete (alarms provided by [AndYouAreWho](http://soundcloud.com/andyouarewho))
|
||||
- Keyboard shortcuts using Mousetrap.js (hit space to pause/resume)
|
||||
- Custom time with adjustable units
|
||||
BIN
public/assets/js/libs/pomodoro/audio/one_bell.mp3
Normal file
BIN
public/assets/js/libs/pomodoro/audio/one_bell.mp3
Normal file
Binary file not shown.
BIN
public/assets/js/libs/pomodoro/audio/one_chime.mp3
Normal file
BIN
public/assets/js/libs/pomodoro/audio/one_chime.mp3
Normal file
Binary file not shown.
BIN
public/assets/js/libs/pomodoro/audio/three_beeps.mp3
Normal file
BIN
public/assets/js/libs/pomodoro/audio/three_beeps.mp3
Normal file
Binary file not shown.
BIN
public/assets/js/libs/pomodoro/audio/three_boops.mp3
Normal file
BIN
public/assets/js/libs/pomodoro/audio/three_boops.mp3
Normal file
Binary file not shown.
BIN
public/assets/js/libs/pomodoro/images/green_tomato.ico
Normal file
BIN
public/assets/js/libs/pomodoro/images/green_tomato.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
BIN
public/assets/js/libs/pomodoro/images/red_tomato.ico
Normal file
BIN
public/assets/js/libs/pomodoro/images/red_tomato.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
104
public/assets/js/libs/pomodoro/pomodoro.css
Normal file
104
public/assets/js/libs/pomodoro/pomodoro.css
Normal file
@@ -0,0 +1,104 @@
|
||||
body {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
}
|
||||
header {
|
||||
padding-bottom: 10px;
|
||||
border-bottom: thin solid #777;
|
||||
font-family: 'Indie Flower', cursive;
|
||||
}
|
||||
label {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 15px;
|
||||
padding: 0;
|
||||
font-family: 'Indie Flower', cursive;
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
footer {
|
||||
padding: 10px 0px;
|
||||
border-top: thin solid #777;
|
||||
}
|
||||
#title {
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
}
|
||||
#subtitle {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.content {
|
||||
padding: 20px 0px 40px 0px;
|
||||
}
|
||||
#timer {
|
||||
font-size: 6em;
|
||||
font-weight: bold;
|
||||
}
|
||||
button.btn_default {
|
||||
padding: 8px 12px;
|
||||
margin: 2px 0px;
|
||||
font-weight: bold;
|
||||
border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border: 1px solid;
|
||||
}
|
||||
#btn_start {
|
||||
background-color: #9F9;
|
||||
border: 1px solid #171;
|
||||
}
|
||||
#btn_pause {
|
||||
background-color: #FF9;
|
||||
border: 1px solid #771;
|
||||
}
|
||||
#btn_reset {
|
||||
background-color: #F99;
|
||||
border: 1px solid #711;
|
||||
}
|
||||
#ipt_custom {
|
||||
padding: 8px 12px;
|
||||
width: 75px;
|
||||
border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border: 1px solid;
|
||||
text-align: center;
|
||||
}
|
||||
#custom_units {
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border: 1px solid;
|
||||
text-align: center;
|
||||
}
|
||||
div.footerbox {
|
||||
max-width: 300px;
|
||||
margin: 10px 5px;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background-color: #EEE;
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
-webkit-border-radius: 8px;
|
||||
border: 1px solid;
|
||||
}
|
||||
div.footerbox ol {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
padding-left: 15px;
|
||||
}
|
||||
#options {
|
||||
text-align: left;
|
||||
}
|
||||
#options label {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#options select {
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.credits {
|
||||
margin: 2em 0;
|
||||
color: #999;
|
||||
}
|
||||
99
public/assets/js/libs/pomodoro/pomodoro.html
Normal file
99
public/assets/js/libs/pomodoro/pomodoro.html
Normal file
@@ -0,0 +1,99 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title id="tab_title">Pomodoro</title>
|
||||
<link id="dynamic-favicon" rel="icon" type="image/ico"
|
||||
href="images/red_tomato.ico">
|
||||
<!-- Original favicon courtesy of http://icons8.com -->
|
||||
<link rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
|
||||
<link rel='stylesheet' type='text/css'
|
||||
href='http://fonts.googleapis.com/css?family=Indie+Flower'>
|
||||
<link rel="stylesheet" href="pomodoro.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div id="titlebox">
|
||||
<div id="title">Pomodoro</div>
|
||||
<div id="subtitle">A simple workflow tool</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="content">
|
||||
<p>
|
||||
<div><span id="timer"></span></div>
|
||||
<button id="btn_start" class="btn_default">start</button>
|
||||
<button id="btn_pause" class="btn_default">pause</button>
|
||||
<button id="btn_reset" class="btn_default">reset</button>
|
||||
</p>
|
||||
<p>
|
||||
<button id="btn_pomodoro" class="btn_default">pomodoro (25m)</button>
|
||||
<button id="btn_shortbreak" class="btn_default">short break (5m)</button>
|
||||
<button id="btn_longbreak" class="btn_default">long break (15m)</button>
|
||||
</p>
|
||||
<p>
|
||||
<button id="btn_custom" class="btn_default">
|
||||
<label for="ipt_custom">custom:</label>
|
||||
</button>
|
||||
<input type="number" id="ipt_custom" value="45" min="0" max="100000000">
|
||||
<select id="custom_units">
|
||||
<option value="seconds">seconds</option>
|
||||
<option value="minutes" selected>minutes</option>
|
||||
<option value="hours">hours</option>
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footerbox">
|
||||
<h1>How it works:</h1>
|
||||
<ol>
|
||||
<li>Choose a task to focus on</li>
|
||||
<li>Work for 25 uninterrupted minutes</li>
|
||||
<li>Break for 5 minutes</li>
|
||||
<li>Every four cycles, take a 15-30 minute<br>
|
||||
break instead, preferably outside</li>
|
||||
</ol>
|
||||
<br>
|
||||
<a href="https://en.wikipedia.org/wiki/Pomodoro_Technique" target="_blank">
|
||||
Read more at Wikipedia
|
||||
</a>
|
||||
</div>
|
||||
<div class="footerbox">
|
||||
<h1>Options:</h1>
|
||||
<div id="options">
|
||||
<label for="alarm_select" id="lbl_alarm">Alarm:</label><br>
|
||||
<select id="alarm_select">
|
||||
<option value="none">None</option>
|
||||
<option value="alarm_chime">Chime</option>
|
||||
<option value="alarm_bell" selected>Bell</option>
|
||||
<option value="alarm_beeps">Beeps</option>
|
||||
<option value="alarm_boops">Boops</option>
|
||||
</select>
|
||||
<br><br>
|
||||
<label for="alarm_volume" id="lbl_volume">Volume:</label><br>
|
||||
<input type="range" id="alarm_volume" min=0 max=100 value=50>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="credits">
|
||||
Created by
|
||||
<a href="../index.html">Andy Roche</a> -
|
||||
<a href="https://github.com/rocheio/rocheio.github.io/tree/master/pomodoro">Github</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<audio id="alarm_chime">
|
||||
<source src="audio/one_chime.mp3" type="audio/mpeg"></audio>
|
||||
<audio id="alarm_bell">
|
||||
<source src="audio/one_bell.mp3" type="audio/mpeg"></audio>
|
||||
<audio id="alarm_beeps">
|
||||
<source src="audio/three_beeps.mp3" type="audio/mpeg"></audio>
|
||||
<audio id="alarm_boops">
|
||||
<source src="audio/three_boops.mp3" type="audio/mpeg"></audio>
|
||||
<!-- Audio courtesy of https://soundcloud.com/andyouarewho -->
|
||||
<script type="text/javascript" src="../resources/mousetrap.js"></script>
|
||||
<script type="text/javascript" src="pomodoro.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
222
public/assets/js/libs/pomodoro/pomodoro.js
Normal file
222
public/assets/js/libs/pomodoro/pomodoro.js
Normal file
@@ -0,0 +1,222 @@
|
||||
/** Represents a timer that can count down. */
|
||||
function CountdownTimer(seconds, tickRate) {
|
||||
this.seconds = seconds || (25*60);
|
||||
this.tickRate = tickRate || 500; // Milliseconds
|
||||
this.tickFunctions = [];
|
||||
this.isRunning = false;
|
||||
this.remaining = this.seconds;
|
||||
|
||||
/** CountdownTimer starts ticking down and executes all tick
|
||||
functions once per tick. */
|
||||
this.start = function() {
|
||||
if (this.isRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isRunning = true;
|
||||
|
||||
// Set variables related to when this timer started
|
||||
var startTime = Date.now(),
|
||||
thisTimer = this;
|
||||
|
||||
// Tick until complete or interrupted
|
||||
(function tick() {
|
||||
secondsSinceStart = ((Date.now() - startTime) / 1000) | 0;
|
||||
var secondsRemaining = thisTimer.remaining - secondsSinceStart;
|
||||
|
||||
// Check if timer has been paused by user
|
||||
if (thisTimer.isRunning === false) {
|
||||
thisTimer.remaining = secondsRemaining;
|
||||
} else {
|
||||
if (secondsRemaining > 0) {
|
||||
// Execute another tick in tickRate milliseconds
|
||||
setTimeout(tick, thisTimer.tickRate);
|
||||
} else {
|
||||
// Stop this timer
|
||||
thisTimer.remaining = 0;
|
||||
thisTimer.isRunning = false;
|
||||
|
||||
// Alert user that time is up
|
||||
playAlarm();
|
||||
changeFavicon('green');
|
||||
}
|
||||
|
||||
var timeRemaining = parseSeconds(secondsRemaining);
|
||||
|
||||
// Execute each tickFunction in the list with thisTimer
|
||||
// as an argument
|
||||
thisTimer.tickFunctions.forEach(
|
||||
function(tickFunction) {
|
||||
tickFunction.call(this,
|
||||
timeRemaining.minutes,
|
||||
timeRemaining.seconds);
|
||||
},
|
||||
thisTimer);
|
||||
}
|
||||
}());
|
||||
};
|
||||
|
||||
/** Pause the timer. */
|
||||
this.pause = function() {
|
||||
this.isRunning = false;
|
||||
};
|
||||
|
||||
/** Pause the timer and reset to its original time. */
|
||||
this.reset = function(seconds) {
|
||||
this.isRunning = false;
|
||||
this.seconds = seconds
|
||||
this.remaining = seconds
|
||||
};
|
||||
|
||||
/** Add a function to the timer's tickFunctions. */
|
||||
this.onTick = function(tickFunction) {
|
||||
if (typeof tickFunction === 'function') {
|
||||
this.tickFunctions.push(tickFunction);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Return minutes and seconds from seconds. */
|
||||
function parseSeconds(seconds) {
|
||||
return {
|
||||
'minutes': (seconds / 60) | 0,
|
||||
'seconds': (seconds % 60) | 0
|
||||
}
|
||||
}
|
||||
|
||||
/** Play the selected alarm at selected volume. */
|
||||
function playAlarm() {
|
||||
var alarmValue = document.getElementById('alarm_select').value;
|
||||
if (alarmValue != 'none') {
|
||||
var alarmAudio = document.getElementById(alarmValue);
|
||||
var alarmVolume = document.getElementById('alarm_volume').value;
|
||||
alarmAudio.volume = alarmVolume / 100;
|
||||
alarmAudio.play();
|
||||
}
|
||||
}
|
||||
|
||||
/** Change the color of the favicon. */
|
||||
function changeFavicon(color) {
|
||||
document.head = document.head || document.getElementsByTagName('head')[0];
|
||||
var color = color || 'green';
|
||||
|
||||
var newFavicon = document.createElement('link'),
|
||||
oldFavicon = document.getElementById('dynamic-favicon');
|
||||
newFavicon.id = 'dynamic-favicon'
|
||||
newFavicon.type = 'image/ico';
|
||||
newFavicon.rel = 'icon';
|
||||
newFavicon.href = 'images/' + color + '_tomato.ico';
|
||||
|
||||
if (oldFavicon) {
|
||||
document.head.removeChild(oldFavicon);
|
||||
}
|
||||
document.head.appendChild(newFavicon);
|
||||
}
|
||||
|
||||
/** Window onload functions. */
|
||||
window.onload = function () {
|
||||
var timerDisplay = document.getElementById('timer'),
|
||||
customTimeInput = document.getElementById('ipt_custom'),
|
||||
timer = new CountdownTimer(),
|
||||
timeObj = parseSeconds(25*60);
|
||||
|
||||
/** Set the time on the main clock display and
|
||||
set the time remaining section in the title. */
|
||||
function setTimeOnAllDisplays(minutes, seconds) {
|
||||
if (minutes >= 60) {
|
||||
// Add an hours section to all displays
|
||||
hours = Math.floor(minutes / 60);
|
||||
minutes = minutes % 60;
|
||||
clockHours = hours + ':';
|
||||
document.title = '(' + hours + 'h' + minutes + 'm) Pomodoro';
|
||||
} else {
|
||||
clockHours = '';
|
||||
document.title = '(' + minutes + 'm) Pomodoro';
|
||||
}
|
||||
|
||||
clockMinutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
clockMinutes += ':';
|
||||
clockSeconds = seconds < 10 ? '0' + seconds : seconds;
|
||||
|
||||
timerDisplay.textContent = clockHours + clockMinutes + clockSeconds;
|
||||
}
|
||||
|
||||
/** Revert the favicon to red, delete the old timer
|
||||
object, and start a new one. */
|
||||
function resetMainTimer(seconds) {
|
||||
changeFavicon('red');
|
||||
timer.pause();
|
||||
timer = new CountdownTimer(seconds);
|
||||
timer.onTick(setTimeOnAllDisplays);
|
||||
}
|
||||
|
||||
// Set default page timer displays
|
||||
setTimeOnAllDisplays(timeObj.minutes, timeObj.seconds);
|
||||
|
||||
timer.onTick(setTimeOnAllDisplays);
|
||||
|
||||
// Add listeners for start, pause, etc. buttons
|
||||
document.getElementById('btn_start').addEventListener(
|
||||
'click', function () {
|
||||
timer.start();
|
||||
});
|
||||
|
||||
document.getElementById('btn_pause').addEventListener(
|
||||
'click', function () {
|
||||
timer.pause();
|
||||
});
|
||||
|
||||
document.getElementById('btn_reset').addEventListener(
|
||||
'click', function () {
|
||||
resetMainTimer(timer.seconds);
|
||||
timer.start();
|
||||
});
|
||||
|
||||
document.getElementById('btn_pomodoro').addEventListener(
|
||||
'click', function () {
|
||||
resetMainTimer(25*60);
|
||||
timer.start();
|
||||
});
|
||||
|
||||
document.getElementById('btn_shortbreak').addEventListener(
|
||||
'click', function () {
|
||||
resetMainTimer(5*60);
|
||||
timer.start();
|
||||
});
|
||||
|
||||
document.getElementById('btn_longbreak').addEventListener(
|
||||
'click', function () {
|
||||
resetMainTimer(15*60);
|
||||
timer.start();
|
||||
});
|
||||
|
||||
document.getElementById('btn_custom').addEventListener(
|
||||
'click', function () {
|
||||
customUnits = document.getElementById('custom_units').value
|
||||
if (customUnits === 'minutes') {
|
||||
resetMainTimer(customTimeInput.value*60);
|
||||
} else if (customUnits === 'hours') {
|
||||
resetMainTimer(customTimeInput.value*3600);
|
||||
} else {
|
||||
resetMainTimer(customTimeInput.value);
|
||||
}
|
||||
timer.start();
|
||||
});
|
||||
|
||||
// Bind keyboard shortcut for starting/pausing timer
|
||||
Mousetrap.bind('space', function(e) {
|
||||
// Remove default behavior of buttons (page scrolling)
|
||||
if (e.preventDefault()) {
|
||||
e.preventDefault();
|
||||
} else {
|
||||
e.returnValue = false; //IE
|
||||
}
|
||||
|
||||
// Pause or start the timer
|
||||
if(timer.isRunning) {
|
||||
timer.pause();
|
||||
} else {
|
||||
timer.start();
|
||||
}
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user