mirror of
https://github.com/urbit/shrub.git
synced 2024-12-01 22:55:03 +03:00
Added Max's timer and clock apps
This commit is contained in:
parent
bcfface83e
commit
cc35305388
@ -51,10 +51,6 @@ class UrbitApi {
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Special actions
|
||||
*/
|
||||
|
||||
permit(cir, aud, message) {
|
||||
this.hall({
|
||||
permit: {
|
||||
@ -103,22 +99,6 @@ class UrbitApi {
|
||||
});
|
||||
}
|
||||
|
||||
message(aud, words) {
|
||||
let msg = {
|
||||
aud,
|
||||
ses: [{
|
||||
lin: {
|
||||
msg: words,
|
||||
pat: false
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.hall({
|
||||
phrase: msg
|
||||
});
|
||||
}
|
||||
|
||||
source(nom, sub) {
|
||||
this.hall({
|
||||
source: {
|
||||
@ -146,37 +126,6 @@ class UrbitApi {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
create(nom, priv) {
|
||||
this.hall({
|
||||
create: {
|
||||
nom: nom,
|
||||
des: "chatroom",
|
||||
sec: priv ? "village" : "channel"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ire(aud, uid, msg) {
|
||||
let message = {
|
||||
aud: aud,
|
||||
ses: [{
|
||||
ire: {
|
||||
top: uid,
|
||||
sep: {
|
||||
lin: {
|
||||
msg: msg,
|
||||
pat: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
this.hall({
|
||||
phrase: message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export let api = new UrbitApi();
|
||||
|
@ -44,7 +44,7 @@
|
||||
|= old=(unit state)
|
||||
^- (quip move _this)
|
||||
?~ old
|
||||
=/ inboxpat /circle/inbox/config/group
|
||||
=/ inboxpat /circle/inbox/config/peers
|
||||
=/ circlespat /circles/[(scot %p our.bol)]
|
||||
=/ inboxi/poke
|
||||
:- %hall-action
|
||||
|
@ -17,6 +17,10 @@
|
||||
return module = { exports: {} }, fn(module, module.exports), module.exports;
|
||||
}
|
||||
|
||||
function getCjsExportFromNamespace (n) {
|
||||
return n && n.default || n;
|
||||
}
|
||||
|
||||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@ -47458,6 +47462,8 @@
|
||||
isBuffer: isBuffer
|
||||
});
|
||||
|
||||
var require$$0 = getCjsExportFromNamespace(bufferEs6);
|
||||
|
||||
var bn = createCommonjsModule(function (module) {
|
||||
(function (module, exports) {
|
||||
|
||||
@ -47510,7 +47516,7 @@
|
||||
|
||||
var Buffer;
|
||||
try {
|
||||
Buffer = bufferEs6.Buffer;
|
||||
Buffer = require$$0.Buffer;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
@ -51744,10 +51750,6 @@ lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes\
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Special actions
|
||||
*/
|
||||
|
||||
permit(cir, aud, message) {
|
||||
this.hall({
|
||||
permit: {
|
||||
@ -51796,22 +51798,6 @@ lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes\
|
||||
});
|
||||
}
|
||||
|
||||
message(aud, words) {
|
||||
let msg = {
|
||||
aud,
|
||||
ses: [{
|
||||
lin: {
|
||||
msg: words,
|
||||
pat: false
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.hall({
|
||||
phrase: msg
|
||||
});
|
||||
}
|
||||
|
||||
source(nom, sub) {
|
||||
this.hall({
|
||||
source: {
|
||||
@ -51839,37 +51825,6 @@ lyrtesmudnytbyrsenwegfyrmurtelreptegpecnelnevfes\
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
create(nom, priv) {
|
||||
this.hall({
|
||||
create: {
|
||||
nom: nom,
|
||||
des: "chatroom",
|
||||
sec: priv ? "village" : "channel"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ire(aud, uid, msg) {
|
||||
let message = {
|
||||
aud: aud,
|
||||
ses: [{
|
||||
ire: {
|
||||
top: uid,
|
||||
sep: {
|
||||
lin: {
|
||||
msg: msg,
|
||||
pat: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
this.hall({
|
||||
phrase: message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let api = new UrbitApi();
|
||||
|
63
apps/clock/.gitignore
vendored
Normal file
63
apps/clock/.gitignore
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
*.swp
|
||||
.DS_Store
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
21
apps/clock/LICENSE
Normal file
21
apps/clock/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 urbit
|
||||
|
||||
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
apps/clock/README.md
Normal file
10
apps/clock/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Weather tile for Urbit
|
||||
|
||||
To install this on your Urbit planet:
|
||||
1. In your Urbit's Dojo, run |mount %
|
||||
2. Write in the filepath to your Urbit's pier in the urbitrc-sample file in this repository, then copy it to .urbitrc in this directory.
|
||||
3. Run `npm install` in terminal in this directory.
|
||||
4. Run `gulp default` in terminal in this directory.
|
||||
5. Run |start %weather in your Urbit's Dojo.
|
||||
|
||||
To see it, navigate to your Urbit's url and add /~home to the URL path.
|
123
apps/clock/gulpfile.js
Normal file
123
apps/clock/gulpfile.js
Normal file
@ -0,0 +1,123 @@
|
||||
var gulp = require('gulp');
|
||||
var cssimport = require('gulp-cssimport');
|
||||
var cssnano = require('gulp-cssnano');
|
||||
var rollup = require('gulp-better-rollup');
|
||||
var sucrase = require('@sucrase/gulp-plugin');
|
||||
var minify = require('gulp-minify');
|
||||
|
||||
var resolve = require('rollup-plugin-node-resolve');
|
||||
var commonjs = require('rollup-plugin-commonjs');
|
||||
var replace = require('rollup-plugin-replace');
|
||||
var json = require('rollup-plugin-json');
|
||||
var builtins = require('rollup-plugin-node-builtins');
|
||||
var rootImport = require('rollup-plugin-root-import');
|
||||
var globals = require('rollup-plugin-node-globals');
|
||||
|
||||
/***
|
||||
Main config options
|
||||
***/
|
||||
|
||||
var urbitrc = require('./.urbitrc');
|
||||
|
||||
/***
|
||||
End main config options
|
||||
***/
|
||||
|
||||
gulp.task('jsx-transform', function(cb) {
|
||||
return gulp.src('src/**/*.js')
|
||||
.pipe(sucrase({
|
||||
transforms: ['jsx']
|
||||
}))
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
gulp.task('tile-jsx-transform', function(cb) {
|
||||
return gulp.src('tile/**/*.js')
|
||||
.pipe(sucrase({
|
||||
transforms: ['jsx']
|
||||
}))
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('js-imports', function(cb) {
|
||||
return gulp.src('dist/index.js')
|
||||
.pipe(rollup({
|
||||
plugins: [
|
||||
commonjs({
|
||||
namedExports: {
|
||||
'node_modules/react/index.js': [ 'Component' ],
|
||||
'node_modules/react-is/index.js': [ 'isValidElementType' ],
|
||||
}
|
||||
}),
|
||||
rootImport({
|
||||
root: `${__dirname}/dist/js`,
|
||||
useEntry: 'prepend',
|
||||
extensions: '.js'
|
||||
}),
|
||||
json(),
|
||||
globals(),
|
||||
builtins(),
|
||||
resolve()
|
||||
]
|
||||
}, 'umd'))
|
||||
.on('error', function(e){
|
||||
console.log(e);
|
||||
cb();
|
||||
})
|
||||
.pipe(gulp.dest('./urbit/app/clock/js/'))
|
||||
.on('end', cb);
|
||||
});
|
||||
|
||||
gulp.task('tile-js-imports', function(cb) {
|
||||
return gulp.src('dist/tile.js')
|
||||
.pipe(rollup({
|
||||
plugins: [
|
||||
commonjs({
|
||||
namedExports: {
|
||||
'node_modules/react/index.js': [ 'Component' ],
|
||||
}
|
||||
}),
|
||||
rootImport({
|
||||
root: `${__dirname}/dist/js`,
|
||||
useEntry: 'prepend',
|
||||
extensions: '.js'
|
||||
}),
|
||||
json(),
|
||||
globals(),
|
||||
builtins(),
|
||||
resolve()
|
||||
]
|
||||
}, 'umd'))
|
||||
.on('error', function(e){
|
||||
console.log(e);
|
||||
cb();
|
||||
})
|
||||
.pipe(gulp.dest('./urbit/app/clock/js/'))
|
||||
.on('end', cb);
|
||||
});
|
||||
|
||||
|
||||
gulp.task('js-minify', function () {
|
||||
return gulp.src('./urbit/app/clock/js/index.js')
|
||||
.pipe(minify())
|
||||
.pipe(gulp.dest('./urbit/app/clock/js/'));
|
||||
});
|
||||
|
||||
gulp.task('urbit-copy', function () {
|
||||
let ret = gulp.src('urbit/**/*');
|
||||
|
||||
urbitrc.URBIT_PIERS.forEach(function(pier) {
|
||||
ret = ret.pipe(gulp.dest(pier));
|
||||
});
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
gulp.task('tile-js-bundle-dev', gulp.series('tile-jsx-transform', 'tile-js-imports'));
|
||||
|
||||
gulp.task('default', gulp.series('tile-js-bundle-dev', 'urbit-copy'));
|
||||
gulp.task('watch', gulp.series('default', function() {
|
||||
gulp.watch('tile/**/*.js', gulp.parallel('tile-js-bundle-dev'));
|
||||
gulp.watch('urbit/**/*', gulp.parallel('urbit-copy'));
|
||||
}));
|
7035
apps/clock/package-lock.json
generated
Normal file
7035
apps/clock/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
37
apps/clock/package.json
Normal file
37
apps/clock/package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "urbit-apps",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@sucrase/gulp-plugin": "^2.0.0",
|
||||
"gulp": "^4.0.0",
|
||||
"rollup": "^1.6.0",
|
||||
"gulp-better-rollup": "^4.0.1",
|
||||
"gulp-cssimport": "^6.0.0",
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-minify": "^3.1.0",
|
||||
"rollup-plugin-commonjs": "^9.2.0",
|
||||
"rollup-plugin-json": "^2.3.0",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
"rollup-plugin-node-globals": "^1.4.0",
|
||||
"rollup-plugin-node-resolve": "^3.4.0",
|
||||
"rollup-plugin-replace": "^2.0.0",
|
||||
"rollup-plugin-root-import": "^0.2.3",
|
||||
"sucrase": "^3.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.5.2",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-router-dom": "^5.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"natives": "1.1.3"
|
||||
}
|
||||
}
|
169
apps/clock/tile/tile.js
Normal file
169
apps/clock/tile/tile.js
Normal file
@ -0,0 +1,169 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const outerSize = 234; //tile size
|
||||
const innerSize = 218; //clock size
|
||||
|
||||
//polar to cartesian
|
||||
var ptc = function(r, theta) {
|
||||
return {
|
||||
x: r * Math.cos(theta),
|
||||
y: r * Math.sin(theta)
|
||||
}
|
||||
}
|
||||
|
||||
class Clock extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.animate = this.animate.bind(this);
|
||||
this.hourHand = this.hourHand.bind(this);
|
||||
this.minuteHand = this.minuteHand.bind(this);
|
||||
this.secondHand = this.secondHand.bind(this);
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.animate()
|
||||
}
|
||||
|
||||
dodecagon(ctx) {
|
||||
var points = [];
|
||||
//first create array of twelve points
|
||||
for(var i = 0; i < 12; i++) {
|
||||
var deg = i * (Math.PI / 6);
|
||||
var p = ptc(innerSize/2, deg);
|
||||
p.x += innerSize/2;
|
||||
p.y += innerSize/2;
|
||||
points[i] = p;
|
||||
}
|
||||
ctx.fillStyle = "white";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
for(var i = 1; i < points.length; i++) {
|
||||
ctx.lineTo(points[i].x,points[i].y);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
hourHand(ctx, time) {
|
||||
//get number of minutes in the day so far, this is so hour hand moves gradually
|
||||
// rather than in large ticks
|
||||
var mins = time.getMinutes() + (60 * time.getHours());
|
||||
|
||||
//draw the circle thing in the middle
|
||||
ctx.fillStyle = "black";
|
||||
ctx.beginPath();
|
||||
ctx.arc(innerSize/2, innerSize/2, 5, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
//draw the actual hour hand
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(innerSize/2, innerSize/2);
|
||||
var angle = (Math.PI/-2.0) + ((2*Math.PI/(12*60)) * mins);
|
||||
var p = ptc(innerSize*.22, angle);
|
||||
p.x += innerSize/2;
|
||||
p.y += innerSize/2;
|
||||
ctx.lineTo(p.x,p.y);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
minuteHand(ctx, time) {
|
||||
//number of seconds in the hour so far
|
||||
var secs = time.getSeconds() + (60 * time.getMinutes());
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(innerSize/2, innerSize/2);
|
||||
var angle = (Math.PI/-2.0) + ((2*Math.PI/(60*60)) * secs);
|
||||
var p = ptc(innerSize*.35, angle);
|
||||
p.x += innerSize/2;
|
||||
p.y += innerSize/2;
|
||||
ctx.lineTo(p.x,p.y);
|
||||
ctx.stroke();
|
||||
|
||||
}
|
||||
|
||||
secondHand(ctx, time) {
|
||||
//get number of ms in minute so far
|
||||
var secs = time.getSeconds();
|
||||
|
||||
let middle = {x: innerSize/2, y: innerSize*.75};
|
||||
//draw the circle thing in the middle
|
||||
ctx.fillStyle = "red";
|
||||
ctx.beginPath();
|
||||
ctx.arc(middle.x, middle.y, 5, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
//draw the actual second hand
|
||||
ctx.strokeStyle = "red";
|
||||
ctx.beginPath();
|
||||
var angle = (Math.PI/-2.0) + ((2*Math.PI/(60)) * secs);
|
||||
var p = ptc(30, angle);
|
||||
var p2 = ptc(-10, angle ); //starting point is a little bit off center in the opposite direction
|
||||
p.x += middle.x;
|
||||
p.y += middle.y;
|
||||
p2.x += middle.x;
|
||||
p2.y += middle.y
|
||||
ctx.moveTo(p2.x, p2.y);
|
||||
ctx.lineTo(p.x,p.y);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
animate() {
|
||||
var time = new Date();
|
||||
//continuously animate
|
||||
var c = document.getElementById("clock-canvas");
|
||||
var ctx = c.getContext("2d");
|
||||
ctx.clearRect(0, 0, c.width, c.height);
|
||||
ctx.save();
|
||||
ctx.translate(0.5, 0.5); //forces antialias thus smoothing out jagged lines
|
||||
|
||||
//draw the clock itself
|
||||
this.dodecagon(ctx);
|
||||
|
||||
//draw the hands
|
||||
this.secondHand(ctx, time);
|
||||
|
||||
this.hourHand(ctx, time);
|
||||
this.minuteHand(ctx, time);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
window.requestAnimationFrame(this.animate)
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div>
|
||||
<canvas id="clock-canvas" width={innerSize} height={innerSize}></canvas>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default class ClockTile extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
renderWrapper(child) {
|
||||
return (
|
||||
<div className="pa2 bg-dark-gray" style={{ width: outerSize, height: outerSize }}>
|
||||
{child}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
let data = !!this.props.data ? this.props.data : {};
|
||||
|
||||
return this.renderWrapper((
|
||||
<Clock/>
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window.clockTile = ClockTile;
|
75
apps/clock/urbit/app/clock.hoon
Normal file
75
apps/clock/urbit/app/clock.hoon
Normal file
@ -0,0 +1,75 @@
|
||||
/+ *server
|
||||
/= tile-js
|
||||
/^ octs
|
||||
/; as-octs:mimes:html
|
||||
/: /===/app/clock/js/tile /js/
|
||||
=, format
|
||||
::
|
||||
|%
|
||||
:: +move: output effect
|
||||
::
|
||||
+$ move [bone card]
|
||||
:: +card: output effect payload
|
||||
::
|
||||
+$ poke
|
||||
$% [%noun [@tas path]]
|
||||
==
|
||||
::
|
||||
+$ card
|
||||
$% [%poke wire dock poke]
|
||||
[%http-response =http-event:http]
|
||||
[%connect wire binding:http-server term]
|
||||
[%diff %json json]
|
||||
==
|
||||
::
|
||||
--
|
||||
::
|
||||
|_ [bol=bowl:gall ~]
|
||||
::
|
||||
++ this .
|
||||
::
|
||||
++ bound
|
||||
|= [wir=wire success=? binding=binding:http-server]
|
||||
^- (quip move _this)
|
||||
[~ this]
|
||||
::
|
||||
++ prep
|
||||
|= old=(unit ~)
|
||||
^- (quip move _this)
|
||||
=/ lismov/(list move) %+ weld
|
||||
`(list move)`[ost.bol %connect / [~ /'~clock'] %clock]~
|
||||
`(list move)`[ost.bol %poke /clock [our.bol %launch] [%noun [%clock /tile]]]~
|
||||
:- lismov
|
||||
this
|
||||
::
|
||||
++ peer-tile
|
||||
|= pax=path
|
||||
^- (quip move _this)
|
||||
[[ost.bol %diff %json *json]~ this]
|
||||
::
|
||||
++ send-tile-diff
|
||||
|= jon=json
|
||||
^- (list move)
|
||||
%+ turn (prey:pubsub:userlib /tile bol)
|
||||
|= [=bone ^]
|
||||
[bone %diff %json jon]
|
||||
::
|
||||
++ poke-handle-http-request
|
||||
%- (require-authorization:app ost.bol move this)
|
||||
|= =inbound-request:http-server
|
||||
^- (quip move _this)
|
||||
=+ request-line=(parse-request-line url.request.inbound-request)
|
||||
=+ back-path=(flop site.request-line)
|
||||
=/ name=@t
|
||||
=+ back-path=(flop site.request-line)
|
||||
?~ back-path
|
||||
''
|
||||
i.back-path
|
||||
::
|
||||
?~ back-path
|
||||
[[ost.bol %http-response not-found:app]~ this]
|
||||
?: =(name 'tile')
|
||||
[[ost.bol %http-response (js-response:app tile-js)]~ this]
|
||||
[[ost.bol %http-response not-found:app]~ this]
|
||||
::
|
||||
--
|
2375
apps/clock/urbit/app/clock/js/tile.js
Normal file
2375
apps/clock/urbit/app/clock/js/tile.js
Normal file
File diff suppressed because it is too large
Load Diff
5
apps/clock/urbitrc-sample
Normal file
5
apps/clock/urbitrc-sample
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
URBIT_PIERS: [
|
||||
"/Users/logan/Dev/light-urbit/build/zod-chess-9/home",
|
||||
]
|
||||
};
|
63
apps/timer/.gitignore
vendored
Normal file
63
apps/timer/.gitignore
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
*.swp
|
||||
.DS_Store
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
21
apps/timer/LICENSE
Normal file
21
apps/timer/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 urbit
|
||||
|
||||
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
apps/timer/README.md
Normal file
10
apps/timer/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Weather tile for Urbit
|
||||
|
||||
To install this on your Urbit planet:
|
||||
1. In your Urbit's Dojo, run |mount %
|
||||
2. Write in the filepath to your Urbit's pier in the urbitrc-sample file in this repository, then copy it to .urbitrc in this directory.
|
||||
3. Run `npm install` in terminal in this directory.
|
||||
4. Run `gulp default` in terminal in this directory.
|
||||
5. Run |start %weather in your Urbit's Dojo.
|
||||
|
||||
To see it, navigate to your Urbit's url and add /~home to the URL path.
|
125
apps/timer/gulpfile.js
Normal file
125
apps/timer/gulpfile.js
Normal file
@ -0,0 +1,125 @@
|
||||
var gulp = require('gulp');
|
||||
var cssimport = require('gulp-cssimport');
|
||||
var cssnano = require('gulp-cssnano');
|
||||
var rollup = require('gulp-better-rollup');
|
||||
var sucrase = require('@sucrase/gulp-plugin');
|
||||
var minify = require('gulp-minify');
|
||||
|
||||
var resolve = require('rollup-plugin-node-resolve');
|
||||
var commonjs = require('rollup-plugin-commonjs');
|
||||
var replace = require('rollup-plugin-replace');
|
||||
var json = require('rollup-plugin-json');
|
||||
var builtins = require('rollup-plugin-node-builtins');
|
||||
var rootImport = require('rollup-plugin-root-import');
|
||||
var globals = require('rollup-plugin-node-globals');
|
||||
|
||||
/***
|
||||
Main config options
|
||||
***/
|
||||
|
||||
var urbitrc = require('./.urbitrc');
|
||||
|
||||
/***
|
||||
End main config options
|
||||
***/
|
||||
gulp.task('css-bundle', function() {
|
||||
return gulp
|
||||
.src('tile/index.css')
|
||||
.pipe(cssimport())
|
||||
.pipe(cssnano())
|
||||
.pipe(gulp.dest('./urbit/app/home/css'));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('tile-jsx-transform', function(cb) {
|
||||
return gulp.src('tile/**/*.js')
|
||||
.pipe(sucrase({
|
||||
transforms: ['jsx']
|
||||
}))
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('js-imports', function(cb) {
|
||||
return gulp.src('dist/index.js')
|
||||
.pipe(rollup({
|
||||
plugins: [
|
||||
commonjs({
|
||||
namedExports: {
|
||||
'node_modules/react/index.js': [ 'Component' ],
|
||||
'node_modules/react-is/index.js': [ 'isValidElementType' ],
|
||||
}
|
||||
}),
|
||||
rootImport({
|
||||
root: `${__dirname}/dist/js`,
|
||||
useEntry: 'prepend',
|
||||
extensions: '.js'
|
||||
}),
|
||||
json(),
|
||||
globals(),
|
||||
builtins(),
|
||||
resolve()
|
||||
]
|
||||
}, 'umd'))
|
||||
.on('error', function(e){
|
||||
console.log(e);
|
||||
cb();
|
||||
})
|
||||
.pipe(gulp.dest('./urbit/app/timer/js/'))
|
||||
.on('end', cb);
|
||||
});
|
||||
|
||||
gulp.task('tile-js-imports', function(cb) {
|
||||
return gulp.src('dist/tile.js')
|
||||
.pipe(rollup({
|
||||
plugins: [
|
||||
commonjs({
|
||||
namedExports: {
|
||||
'node_modules/react/index.js': [ 'Component' ],
|
||||
}
|
||||
}),
|
||||
rootImport({
|
||||
root: `${__dirname}/dist/js`,
|
||||
useEntry: 'prepend',
|
||||
extensions: '.js'
|
||||
}),
|
||||
json(),
|
||||
globals(),
|
||||
builtins(),
|
||||
resolve()
|
||||
]
|
||||
}, 'umd'))
|
||||
.on('error', function(e){
|
||||
console.log(e);
|
||||
cb();
|
||||
})
|
||||
.pipe(gulp.dest('./urbit/app/timer/js/'))
|
||||
.on('end', cb);
|
||||
});
|
||||
|
||||
|
||||
gulp.task('js-minify', function () {
|
||||
return gulp.src('./urbit/app/timer/js/index.js')
|
||||
.pipe(minify())
|
||||
.pipe(gulp.dest('./urbit/app/timer/js/'));
|
||||
});
|
||||
|
||||
gulp.task('urbit-copy', function () {
|
||||
let ret = gulp.src('urbit/**/*');
|
||||
|
||||
urbitrc.URBIT_PIERS.forEach(function(pier) {
|
||||
ret = ret.pipe(gulp.dest(pier));
|
||||
});
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
gulp.task('tile-js-bundle-dev', gulp.series('tile-jsx-transform', 'tile-js-imports'));
|
||||
|
||||
gulp.task('default', gulp.series('tile-js-bundle-dev', 'urbit-copy'));
|
||||
gulp.task('watch', gulp.series('default', function() {
|
||||
gulp.watch('tile/**/*.js', gulp.parallel('tile-js-bundle-dev'));
|
||||
gulp.watch('tile/**/*.css', gulp.parallel('css-bundle'));
|
||||
|
||||
gulp.watch('urbit/**/*', gulp.parallel('urbit-copy'));
|
||||
}));
|
6887
apps/timer/package-lock.json
generated
Normal file
6887
apps/timer/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
apps/timer/package.json
Normal file
38
apps/timer/package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "urbit-apps",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@sucrase/gulp-plugin": "^2.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-better-rollup": "^4.0.1",
|
||||
"gulp-cssimport": "^6.0.0",
|
||||
"gulp-cssnano": "^2.1.2",
|
||||
"gulp-minify": "^3.1.0",
|
||||
"rollup": "^1.6.0",
|
||||
"rollup-plugin-commonjs": "^9.2.0",
|
||||
"rollup-plugin-json": "^2.3.0",
|
||||
"rollup-plugin-node-builtins": "^2.1.2",
|
||||
"rollup-plugin-node-globals": "^1.4.0",
|
||||
"rollup-plugin-node-resolve": "^3.4.0",
|
||||
"rollup-plugin-replace": "^2.0.0",
|
||||
"rollup-plugin-root-import": "^0.2.3",
|
||||
"sucrase": "^3.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.6",
|
||||
"react": "^16.5.2",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-router-dom": "^5.0.0",
|
||||
"styled-components": "^4.2.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"natives": "1.1.3"
|
||||
}
|
||||
}
|
40
apps/timer/tile/api.js
Normal file
40
apps/timer/tile/api.js
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
class Api {
|
||||
bind(app, path, success, fail, ship) {
|
||||
window.urb.subscribe(ship, app, path,
|
||||
(err) => {
|
||||
fail(err, app, path, ship);
|
||||
},
|
||||
(event) => {
|
||||
success({
|
||||
data: event,
|
||||
from: {
|
||||
app,
|
||||
ship,
|
||||
path
|
||||
}
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
fail(err, app, path, ship);
|
||||
});
|
||||
}
|
||||
|
||||
chess(data) {
|
||||
this.action("chess", "chess-command", data);
|
||||
}
|
||||
|
||||
action(appl, mark, data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.urb.poke(ship, appl, mark, data,
|
||||
(json) => {
|
||||
resolve(json);
|
||||
},
|
||||
(err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Api();
|
27
apps/timer/tile/components/flashing.js
Normal file
27
apps/timer/tile/components/flashing.js
Normal file
@ -0,0 +1,27 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class Flashing extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.alive = true;
|
||||
this.state = { color: "black" };
|
||||
}
|
||||
|
||||
//memory cleanup
|
||||
componentWillUnmount() {
|
||||
this.alive = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
setTimeout(()=>{
|
||||
if(this.alive) {
|
||||
if(this.state.color == "black") { this.setState({color: "white"}) }
|
||||
else if(this.state.color == "white") { this.setState({color: "black"}) }
|
||||
}
|
||||
},400);
|
||||
|
||||
return <div style={{ color: this.state.color }}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
}
|
||||
}
|
37
apps/timer/tile/components/volume-icon.js
Normal file
37
apps/timer/tile/components/volume-icon.js
Normal file
@ -0,0 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class VolumeIcon extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.toggleSound = this.toggleSound.bind(this);
|
||||
}
|
||||
|
||||
|
||||
toggleSound() {
|
||||
this.props.parent.setState( {playSound: !this.props.parent.state.playSound} )
|
||||
}
|
||||
|
||||
render() {
|
||||
let on = this.props.parent.state.playSound;
|
||||
return <div> <a onClick={()=> {
|
||||
this.toggleSound()}}>
|
||||
<img src=
|
||||
{
|
||||
on
|
||||
?
|
||||
"~timer/img/volume-high.png"
|
||||
:
|
||||
"~timer/img/volume-mute.png"
|
||||
}
|
||||
style={{
|
||||
width:"30px",
|
||||
height:"30px"
|
||||
}}
|
||||
></img>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
}
|
282
apps/timer/tile/tile.js
Normal file
282
apps/timer/tile/tile.js
Normal file
@ -0,0 +1,282 @@
|
||||
import React, { Component } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import api from './api';
|
||||
import VolumeIcon from './components/volume-icon';
|
||||
import Flashing from './components/flashing';
|
||||
|
||||
const timerLength = 10000;
|
||||
const outerSize = 234; //size of tile itself
|
||||
const innerSize = 200; //diameter of pomodoro
|
||||
|
||||
//not sure if this should be imported somehow or if copy and paste is the way to go
|
||||
function daToDate(st) {
|
||||
var dub = function(n) {
|
||||
return parseInt(n) < 10 ? "0" + parseInt(n) : n.toString();
|
||||
};
|
||||
var da = st.split('..');
|
||||
var bigEnd = da[0].split('.');
|
||||
var lilEnd = da[1].split('.');
|
||||
var ds = `${bigEnd[0].slice(1)}-${dub(bigEnd[1])}-${dub(bigEnd[2])}T${dub(lilEnd[0])}:${dub(lilEnd[1])}:${dub(lilEnd[2])}Z`;
|
||||
return new Date(ds);
|
||||
}
|
||||
|
||||
//polar to cartesian
|
||||
var ptc = function(r, theta) {
|
||||
return {
|
||||
x: r * Math.cos(theta),
|
||||
y: r * Math.sin(theta)
|
||||
}
|
||||
}
|
||||
|
||||
export default class TimerTile extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.animate = this.animate.bind(this);
|
||||
this.state = this.getStateFromProps(props);
|
||||
this.state.playSound = true;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.animate()
|
||||
}
|
||||
|
||||
getStateFromProps(props) {
|
||||
if(props.data.charAt(0) == "~"){
|
||||
return {mode: "running", startTime: daToDate(props.data).getTime(), time: timerLength};
|
||||
}
|
||||
else if(props.data == "alarm" ) {
|
||||
//api still delivers alarm events for cancelled timers, so make sure that it's actually time to fire the alarm before doing so
|
||||
if( this.state && this.state.mode == "running" && this.state.time < 500 ) {
|
||||
return {mode: "alarm", time:0};
|
||||
}
|
||||
else {
|
||||
if(!this.state) { return {mode: "waiting", time: timerLength} }
|
||||
else {
|
||||
//no change
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {mode: "waiting", time: timerLength};
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
this.setState(this.getStateFromProps(newProps));
|
||||
}
|
||||
|
||||
greenPart(ctx) {
|
||||
//green thing on the tomato that rotates
|
||||
const lightGreen = "#4da97a";
|
||||
const darkGreen = "#386f55";
|
||||
|
||||
//define center of sprout based on time elapsed
|
||||
var ratio = (timerLength-this.state.time) / timerLength; //ratio of elapsed time to total time
|
||||
|
||||
var easedRatio = ( -( Math.cos( Math.PI * ratio ) - 1 ) / 4) + (ratio/2);
|
||||
//from here https://easings.net/en#easeInOutSine
|
||||
|
||||
|
||||
//define scale based on time elapsed
|
||||
var easedRatioCubic = ratio < 0.5 ?
|
||||
4 * ratio * ratio * ratio :
|
||||
1 - Math.pow( -2 * ratio + 2, 3 ) / 2;
|
||||
|
||||
var xCurve = outerSize/2-(.45*innerSize)*Math.sqrt(1-Math.pow((2*easedRatioCubic)-1,2));
|
||||
var center = {x: xCurve, y: .95*innerSize*easedRatioCubic +1.4*(outerSize-innerSize)/2,};
|
||||
|
||||
var symmetricalEasedRatio = easedRatioCubic > .5 ? 1 - ((easedRatioCubic+ratio)/2) : ((easedRatioCubic+ratio)/2);
|
||||
var scale = 1 + symmetricalEasedRatio*.6;
|
||||
|
||||
|
||||
var rotation = ((ratio+easedRatio)/2) * -1 * Math.PI;
|
||||
|
||||
//generate star shape thing
|
||||
var points = [];
|
||||
for(var i = 0; i < 14; i++) {
|
||||
var deg = i * (Math.PI / 7);
|
||||
var p = ptc( i % 2 == 0 ? 15 : 40, deg);
|
||||
|
||||
|
||||
points[i] = p;
|
||||
}
|
||||
|
||||
ctx.save()
|
||||
ctx.translate(center.x, center.y)
|
||||
ctx.rotate(rotation);
|
||||
ctx.scale(scale, scale/2);
|
||||
|
||||
ctx.fillStyle = lightGreen;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(points[0].x, points[0].y);
|
||||
for(var i = 1; i < points.length; i++) {
|
||||
ctx.lineTo(points[i].x,points[i].y);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
|
||||
//draw the circle thing in the middle
|
||||
ctx.fillStyle = darkGreen;
|
||||
ctx.beginPath();
|
||||
|
||||
function drawEllipse(ctx, x, y, w, h) {
|
||||
var kappa = .5522848,
|
||||
ox = (w / 2) * kappa, // control point offset horizontal
|
||||
oy = (h / 2) * kappa, // control point offset vertical
|
||||
xe = x + w, // x-end
|
||||
ye = y + h, // y-end
|
||||
xm = x + w / 2, // x-middle
|
||||
ym = y + h / 2; // y-middle
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, ym);
|
||||
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
|
||||
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
|
||||
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
|
||||
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
|
||||
//ctx.closePath(); // not used correctly, see comments (use to close off open path)
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
drawEllipse(ctx,-5,-5,10,10);
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
animate() {
|
||||
//continuously animate
|
||||
var c = document.getElementById("timer-canvas");
|
||||
var ctx = c.getContext("2d");
|
||||
|
||||
//clear
|
||||
ctx.clearRect(0, 0, c.width, c.height);
|
||||
|
||||
//draw body of pomodoro clock
|
||||
ctx.fillStyle = "#ee5432";
|
||||
ctx.beginPath();
|
||||
ctx.arc(outerSize/2, outerSize/2, innerSize/2, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
//draw line separating top from bottom
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo((outerSize-innerSize)/2, outerSize/2);
|
||||
ctx.lineTo(innerSize+(outerSize-innerSize)/2,outerSize/2);
|
||||
ctx.stroke();
|
||||
|
||||
this.greenPart(ctx);
|
||||
|
||||
if(this.state.mode == "running") {
|
||||
var time = -1 * ((new Date()).getTime() - this.state.startTime);
|
||||
//javascript time can be ahead of the urbit alarm, so we dont want to show negative nubmers
|
||||
if(time < 0) { time = 0; }
|
||||
this.setState({time: time})
|
||||
}
|
||||
window.requestAnimationFrame(this.animate)
|
||||
|
||||
}
|
||||
|
||||
formatTime(time) {
|
||||
var seconds = Math.ceil(time / 1000); //rounding up seems to result in better UX
|
||||
var minutes = Math.floor(seconds / 60);
|
||||
|
||||
//convert to string
|
||||
seconds += "";
|
||||
minutes += "";
|
||||
|
||||
if(seconds.length == 1) { seconds = "0" + seconds }
|
||||
if(minutes.length == 1) { minutes = "0" + minutes }
|
||||
|
||||
return minutes + ":" + seconds;
|
||||
}
|
||||
|
||||
startTimer() {
|
||||
api.action('timer', 'json', 'start');
|
||||
}
|
||||
|
||||
stopTimer() {
|
||||
api.action('timer', 'json', 'stop');
|
||||
}
|
||||
|
||||
renderWrapper(child) {
|
||||
return (
|
||||
<div className="bg-dark-gray" style={{ width: outerSize, height: outerSize }}>
|
||||
{child}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
var interaction;
|
||||
var interactionStyle = "link underline black hover-white";
|
||||
if(this.state.mode == "running") {
|
||||
interaction = <a className={interactionStyle} onClick={this.stopTimer}>Stop</a>;
|
||||
}
|
||||
else if(this.state.mode == "alarm") {
|
||||
interaction = <a className={interactionStyle} onClick={this.stopTimer}>Shhh</a>;
|
||||
}
|
||||
else {
|
||||
interaction = <a className={interactionStyle} onClick={this.startTimer}>Start</a>;
|
||||
|
||||
}
|
||||
|
||||
return this.renderWrapper((
|
||||
<div style={{ position: "relative",
|
||||
fontFamily: "-apple-system,BlinkMacSystemFont,avenir next,avenir,helvetica neue,helvetica,ubuntu,roboto,noto,segoe ui,arial,sans-serif"
|
||||
}}>
|
||||
<canvas id="timer-canvas" width={outerSize} height={outerSize}></canvas>
|
||||
|
||||
<div id="timer-display" style={{
|
||||
width: "100%",
|
||||
textAlign: "center",
|
||||
position: "absolute",
|
||||
top: "120px",
|
||||
left: "0px",
|
||||
fontSize:"28px",
|
||||
fontWeight:"300"
|
||||
}}>
|
||||
{this.state.mode == "running" ? this.formatTime(this.state.time) :
|
||||
this.state.mode == "alarm" ?
|
||||
<div>
|
||||
<Flashing>00:00</Flashing>
|
||||
{
|
||||
this.state.playSound
|
||||
?
|
||||
<audio src="http://maxwellsfoley.com/ding.mp3" loop={true} autoPlay/>
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
:
|
||||
'00:00'}
|
||||
</div>
|
||||
<div id="timer-interact" style={{
|
||||
width: "100%",
|
||||
textAlign: "center",
|
||||
position: "absolute",
|
||||
top: "170px",
|
||||
left: "0px",
|
||||
fontSize:"16px"
|
||||
}}>
|
||||
{ interaction }
|
||||
</div>
|
||||
<div id="volume-container" style={{
|
||||
position: "absolute",
|
||||
top: "200px",
|
||||
left: "5px"
|
||||
}}>
|
||||
<VolumeIcon parent={this}/>
|
||||
</div>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window.timerTile = TimerTile;
|
124
apps/timer/urbit/app/timer.hoon
Normal file
124
apps/timer/urbit/app/timer.hoon
Normal file
@ -0,0 +1,124 @@
|
||||
/+ *server
|
||||
/= tile-js
|
||||
/^ octs
|
||||
/; as-octs:mimes:html
|
||||
/: /===/app/timer/js/tile /js/
|
||||
/= timer-png
|
||||
/^ (map knot @)
|
||||
/: /===/app/timer/img /_ /png/
|
||||
=, format
|
||||
::
|
||||
|%
|
||||
:: +move: output effect
|
||||
::
|
||||
+$ move [bone card]
|
||||
:: +card: output effect payload
|
||||
::
|
||||
+$ poke
|
||||
$% [%noun [@tas path]]
|
||||
==
|
||||
::
|
||||
+$ card
|
||||
$% [%poke wire dock poke]
|
||||
[%http-response =http-event:http]
|
||||
[%connect wire binding:http-server term]
|
||||
[%diff %json json]
|
||||
[%wait wire @da]
|
||||
[%rest wire @da]
|
||||
==
|
||||
::
|
||||
--
|
||||
::
|
||||
|_ [bol=bowl:gall tim=@da]
|
||||
::
|
||||
++ this .
|
||||
::
|
||||
++ bound
|
||||
|= [wir=wire success=? binding=binding:http-server]
|
||||
^- (quip move _this)
|
||||
[~ this]
|
||||
::
|
||||
++ prep
|
||||
|= old=(unit tim=@da)
|
||||
^- (quip move _this)
|
||||
~& 'prep timer'
|
||||
=/ lismov/(list move) %+ weld
|
||||
`(list move)`[ost.bol %connect / [~ /'~timer'] %timer]~
|
||||
`(list move)`[ost.bol %poke /timer [our.bol %launch] [%noun [%timer /tile]]]~
|
||||
:- lismov
|
||||
?~ old
|
||||
this
|
||||
%= this
|
||||
tim tim.u.old
|
||||
==
|
||||
::
|
||||
++ peer-tile
|
||||
|= pax=path
|
||||
^- (quip move _this)
|
||||
?: =(tim *@da)
|
||||
[[ost.bol %diff %json [%s '']]~ this]
|
||||
[[ost.bol %diff %json [%s (scot %da tim)]]~ this]
|
||||
::
|
||||
++ send-tile-diff
|
||||
|= jon=json
|
||||
^- (list move)
|
||||
%+ turn (prey:pubsub:userlib /tile bol)
|
||||
|= [=bone ^]
|
||||
[bone %diff %json jon]
|
||||
::
|
||||
++ poke-json
|
||||
|= jon=json
|
||||
^- (quip move _this)
|
||||
~& jon
|
||||
?. ?=(%s -.jon)
|
||||
[~ this]
|
||||
=/ str/@t +.jon
|
||||
?: =(str 'start')
|
||||
=/ data/@da (add now.bol ~s10)
|
||||
:- %+ weld
|
||||
`(list move)`(send-tile-diff [%s (scot %da data)])
|
||||
`(list move)`[ost.bol %wait /timer data]~
|
||||
this(tim data)
|
||||
?: =(str 'stop')
|
||||
:- %+ weld
|
||||
`(list move)`(send-tile-diff [%s ''])
|
||||
`(list move)`[ost.bol %rest /timer tim]~
|
||||
this(tim *@da)
|
||||
[~ this]
|
||||
::
|
||||
++ poke-handle-http-request
|
||||
%- (require-authorization:app ost.bol move this)
|
||||
|= =inbound-request:http-server
|
||||
^- (quip move _this)
|
||||
=+ request-line=(parse-request-line url.request.inbound-request)
|
||||
=+ back-path=(flop site.request-line)
|
||||
=/ name=@t
|
||||
=+ back-path=(flop site.request-line)
|
||||
?~ back-path
|
||||
''
|
||||
i.back-path
|
||||
::
|
||||
~& site.request-line
|
||||
?+ site.request-line
|
||||
[[ost.bol %http-response not-found:app]~ this]
|
||||
::
|
||||
:: tile
|
||||
::
|
||||
[%'~timer' %tile ~]
|
||||
[[ost.bol %http-response (js-response:app tile-js)]~ this]
|
||||
::
|
||||
:: images
|
||||
::
|
||||
[%'~timer' %img *]
|
||||
=/ img (as-octs:mimes:html (~(got by timer-png) `@ta`name))
|
||||
:_ this
|
||||
[ost.bol %http-response (png-response:app img)]~
|
||||
==
|
||||
::
|
||||
++ wake
|
||||
|= [wir=wire err=(unit tang)]
|
||||
^- (quip move _this)
|
||||
:- (send-tile-diff [%s 'alarm'])
|
||||
this(tim *@da)
|
||||
::
|
||||
--
|
BIN
apps/timer/urbit/app/timer/img/example.png
Normal file
BIN
apps/timer/urbit/app/timer/img/example.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
apps/timer/urbit/app/timer/img/volume-high.png
Normal file
BIN
apps/timer/urbit/app/timer/img/volume-high.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
apps/timer/urbit/app/timer/img/volume-mute.png
Normal file
BIN
apps/timer/urbit/app/timer/img/volume-mute.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
2588
apps/timer/urbit/app/timer/js/tile.js
Normal file
2588
apps/timer/urbit/app/timer/js/tile.js
Normal file
File diff suppressed because it is too large
Load Diff
5
apps/timer/urbitrc-sample
Normal file
5
apps/timer/urbitrc-sample
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
URBIT_PIERS: [
|
||||
"/Users/logan/Dev/light-urbit/build/zod-chess-9/home",
|
||||
]
|
||||
};
|
Loading…
Reference in New Issue
Block a user