calenderwatch_client/js/app.js
Raphael Maenle d6732ea134 adds download from personal server
- pulls calendar json file from (non http) server
2020-04-05 16:16:43 +02:00

485 lines
16 KiB
JavaScript

/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var events;
var eventsTimeStamp = 0;
(function() {
var canvasLayout,
canvasContent,
ctxLayout,
ctxContent,
center,
watchRadius;
function readJSON(path) {
var xhr = new XMLHttpRequest();
xhr.open('GET', path, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 0) {
var file = new File([this.response], 'temp');
var fileReader = new FileReader();
fileReader.addEventListener('load', function(){
events = JSON.parse(fileReader.result);
var onError = function(e) {
console.log('Error!' + e.message);
};
var onResolveSuccess = function(dir) {
var onListFilesSuccess = function(files) {
files.forEach(function(file) {
if (!file.isDirectory) {
dir.deleteFile(file.fullPath, onDeleteSuccess, onError);
}
});
};
dir.listFiles(onListFilesSuccess, onError);
};
var onDeleteSuccess = function() {};
tizen.filesystem.resolve('/opt/usr/media/Downloads', onResolveSuccess, onError);
});
fileReader.readAsText(file);
}
}
xhr.send();
}
function getJSON() {
var downloadRequest = new tizen.DownloadRequest('http://192.168.68.103.xip.io:1234/userinfo/107971745944668140075/calendarevents.json', 'downloads');
tizen.systeminfo.getPropertyValue('NETWORK', function(networkInfo) {
if (networkInfo.networkType === 'NONE') {
console.log('Network connection is not available.Download is not possible.');
downloadRequest = null;
}
});
var listener = {
/* When the download progresses (interval is platform-dependent) */
onprogress: function(id, receivedSize, totalSize) {
console.log('progress for id: ' + id);
console.log('received: ' + receivedSize + ", total: " + totalSize);
},
/* When the user pauses the download */
onpaused: function(id) {
console.log('Paused with id: ' + id);
},
/* When the user cancels the download */
oncanceled: function(id) {
console.log('Canceled with id: ' + id);
},
/* When the download is completed */
oncompleted: function(id, fullPath) {
console.log('Completed with id: ' + id + ', full path: ' + fullPath);
readJSON(fullPath);
},
/* When the download fails */
onfailed: function(id, error) {
console.log('Failed with id: ' + id + ', error name: ' + error.name);
}
};
downloadId = tizen.download.start(downloadRequest, listener);
}
/**
* Renders a circle with specific center, radius, and color
* @private
* @param {object} context - the context for the circle to be placed in
* @param {number} radius - the radius of the circle
* @param {string} color - the color of the circle
*/
function renderCircle(context, center, radius, color) {
context.save();
context.beginPath();
context.fillStyle = color;
context.arc(center.x, center.y, radius, 0, 2 * Math.PI);
context.fill();
context.closePath();
context.restore();
}
/**
* Renders a partial with specific center, radius, and color
* @private
* @param {object} context - the context for the circle to be placed in
* @param {number} radius - the radius of the circle
* @param {string} color - the color of the circle
*/
function renderArc(context, center, radius, color, startAngle, endAngle, hardStart, hardStop) {
if(hardStart == undefined)
hardStart = false;
if(hardStop == undefined)
hardStop= false;
context.save();
context.beginPath();
seperation = 5;
if(!hardStart)
startAngle += seperation;
if(startAngle >= 360)
startAngle -= 360;
if(!hardStop)
endAngle -= seperation;
if(endAngle<0)
endAngle += 360;
context.arc(center.x, center.y, radius, startAngle * Math.PI / 180., endAngle * Math.PI / 180.);
context.fillStyle = color;
context.strokeStyle = color;
context.lineWidth = 18;
context.stroke();
context.restore();
if(!hardStart)
renderCircle(context, polToCart(radius, startAngle), 9, color);
if(!hardStop)
renderCircle(context, polToCart(radius, endAngle), 9, color);
}
function polToCart(radius, angle) {
pos = {
x: center.x + radius * Math.cos(angle * Math.PI / 180),
y: center.y + radius * Math.sin(angle * Math.PI / 180)
};
return pos;
}
function hourToAngle(hour) {
if(hour >= 18)
hour -= 18;
else
hour += 6;
angle = (hour) * 15;
return angle;
}
function minuteToAngle(minute) {
if(minute >= 15)
minute -= 15;
else
minute += 45;
angle = (minute / 60) * 360;
return angle;
}
/**
* Renders a needle with specific center, angle, start point, end point, width and color
* @private
* @param {object} context - the context for the needle to be placed in
* @param {number} angle - the angle of the needle (0 ~ 360)
* @param {number} startPoint - the start point of the needle (-1.0 ~ 1.0)
* @param {number} startPoint - the end point of the needle (-1.0 ~ 1.0)
* @param {number} width - the width of the needle
* @param {string} color - the color of the needle
*/
function renderNeedle(context, angle, startPoint, endPoint, width, color) {
var radius = context.canvas.width / 2,
centerX = context.canvas.width / 2,
centerY = context.canvas.height / 2,
dxi = radius * Math.cos(angle) * startPoint,
dyi = radius * Math.sin(angle) * startPoint,
dxf = radius * Math.cos(angle) * endPoint,
dyf = radius * Math.sin(angle) * endPoint;
context.save();
context.beginPath();
context.lineWidth = width;
context.strokeStyle = color;
context.moveTo(centerX + dxi, centerY + dyi);
context.lineTo(centerX + dxf, centerY + dyf);
context.stroke();
context.closePath();
context.restore();
}
/**
* Renders the 24h sun around the watch
*/
function renderSun(date, hour, minute, second) {
if(hour > 6 && hour < 18)
sunColor = "#FFD700";
else {
sunColor = "#C0C0C0"
}
sunDistance = document.body.clientWidth / 2 - 60;
renderCircle(ctxContent, polToCart(sunDistance, hourToAngle(hour + minute / 60)), 16, sunColor);
}
function renderEarth(date, minute, second) {
earthColor = "#0077BE";
earthDistance = document.body.clientWidth / 2 - 120;
renderCircle(ctxContent, polToCart(earthDistance, minuteToAngle(minute + second / 60)), 10, earthColor);
}
/**
* Renders text at a specific center, radius, and color
* @private
* @param {object} context - the context for the text to be placed in
* @param {string} text - the text to be placed
* @param {number} x - the x-coordinate of the text
* @param {number} y - the y-coordinate of the text
* @param {number} textSize - the size of the text in pixel
* @param {string} color - the color of the text
*/
function renderText(context, text, x, y, textSize, color) {
context.save();
context.beginPath();
context.font = textSize + "px Courier";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = color;
context.fillText(text, x, y);
context.closePath();
context.restore();
}
/**
* Draws the basic layout of the watch
* @private
*/
function drawWatchLayout() {
var grd,
angle,
i,
j;
// Clear canvas
ctxLayout.clearRect(0, 0, ctxLayout.canvas.width, ctxLayout.canvas.height);
// Draw the background circle
/*
renderCircle(ctxLayout, center, watchRadius, "#000000");
grd = ctxLayout.createLinearGradient(0, 0, watchRadius * 2, 0);
grd.addColorStop(0, "#000000");
grd.addColorStop(0.5, "#454545");
grd.addColorStop(1, "#000000");
ctxLayout.fillStyle = grd;
renderCircle(ctxLayout, center, watchRadius * 0.945, grd);
renderCircle(ctxLayout, center, watchRadius * 0.7, "#000000");
*/
// Draw the dividers
// 60 unit divider
/*
for (i = 1; i <= 60; i++) {
angle = (i - 15) * (Math.PI * 2) / 60;
renderNeedle(ctxLayout, angle, 0.95, 1.0, 1, "#c4c4c4");
}
// 12 unit divider
for (j = 1; j <= 12; j++) {
angle = (j - 3) * (Math.PI * 2) / 12;
renderNeedle(ctxLayout, angle, 0.7, 0.945, 10, "#c4c4c4");
}
*/
// renderText(ctxLayout, "TIZEN WATCH", center.x, center.y - (watchRadius * 0.4), 25, "#999999");
}
/**
* Draws the content of the watch
* @private
*/
function drawWatchContent() {
var datetime = tizen.time.getCurrentDateTime(),
hour = datetime.getHours(),
minute = datetime.getMinutes(),
second = datetime.getSeconds(),
date = datetime.getDate();
// Clear canvas
ctxContent.clearRect(0, 0, ctxContent.canvas.width, ctxContent.canvas.height);
// Draw the hour needle
renderSun(date, hour, minute, second);
// Draw the minute needle
renderEarth(ctxContent, minute, second);
// renderNeedle(ctxContent, Math.PI * (((minute + second / 60) / 30) - 0.5), 0, 0.70, 3, "#454545");
// Draw the minute/hour circle
// renderCircle(ctxContent, center, 8, "#454545");
// Draw the second needle
// ctxContent.shadowOffsetX = 4;
// ctxContent.shadowOffsetY = 4;
// renderNeedle(ctxContent, Math.PI * ((second / 30) - 0.5), -0.10, 0.85, 1, "#c4c4c4");
// Draw the second circle
// ctxContent.shadowOffsetX = 0;
// ctxContent.shadowOffsetY = 0;
// renderCircle(ctxContent, center, 5, "#c4c4c4");
// Draw the center circle
// renderCircle(ctxContent, center, 2, "#454545");
// Draw the text for date
// renderText(ctxContent, date, center.x, center.y + (watchRadius * 0.5), 25, "#999999");
if(events == null)
return;
thickness = 18;
edge = document.body.clientWidth / 2 - thickness / 2 - 2;
for(var event in events.events){
var startedBeforeToday = false;
var endsAfterToday = false;
var e = events.events[event];
// check if not today
if(e.startDateTime.date.year != tizen.time.getCurrentDateTime().getFullYear() ||
e.startDateTime.date.month != tizen.time.getCurrentDateTime().getMonth() + 1 ||
e.startDateTime.date.day != tizen.time.getCurrentDateTime().getDate()){
// if not today, check if it is an earlier event
if(e.startDateTime.date.year < tizen.time.getCurrentDateTime().getFullYear())
startedBeforeToday = true;
else if(e.startDateTime.date.month < tizen.time.getCurrentDateTime().getMonth() + 1)
startedBeforeToday = true;
else if(e.startDateTime.date.day < tizen.time.getCurrentDateTime().getDate())
startedBeforeToday = true;
else
continue;
}
// check if not today
if(e.stopDateTime.date.year != tizen.time.getCurrentDateTime().getFullYear() ||
e.stopDateTime.date.month != tizen.time.getCurrentDateTime().getMonth() + 1 ||
e.stopDateTime.date.day != tizen.time.getCurrentDateTime().getDate()){
// if not check if later date
if(e.startDateTime.date.year > tizen.time.getCurrentDateTime().getFullYear())
endsAfterToday = true;
else if(e.startDateTime.date.month > tizen.time.getCurrentDateTime().getMonth() + 1)
endsAfterToday = true;
else if(e.startDateTime.date.day > tizen.time.getCurrentDateTime().getDate())
endsAfterToday = true;
else
continue;
}
if(startedBeforeToday && endsAfterToday)
continue;
var startTime = 0;
if(!startedBeforeToday)
startTime = e.startDateTime.time.hour + e.startDateTime.time.minute / 60;
var stopTime = 0;
if(!endsAfterToday)
stopTime = e.stopDateTime.time.hour + e.stopDateTime.time.minute / 60;
renderArc(ctxContent, center, edge, e.color, hourToAngle(startTime), hourToAngle(stopTime), startedBeforeToday, endsAfterToday);
}
}
function updateCalendar(offset_ms) {
var d = new Date();
var currentTime = d.getTime();
console.log("current Time: " + currentTime);
if(eventsTimeStamp + offset_ms < currentTime){
console.log("updating Events");
getJSON();
eventsTimeStamp = currentTime;
}
}
/**
* Set default variables
* @private
*/
function setDefaultVariables() {
canvasLayout = document.querySelector("#canvas-layout");
ctxLayout = canvasLayout.getContext("2d");
canvasContent = document.querySelector("#canvas-content");
ctxContent = canvasContent.getContext("2d");
// Set the canvases square
canvasLayout.width = document.body.clientWidth;
canvasLayout.height = canvasLayout.width;
canvasContent.width = document.body.clientWidth;
canvasContent.height = canvasContent.width;
center = {
x: document.body.clientWidth / 2,
y: document.body.clientHeight / 2
};
watchRadius = canvasLayout.width / 2;
}
/**
* Set default event listeners
* @private
*/
function setDefaultEvents() {
// add eventListener to update the screen immediately when the device wakes up
document.addEventListener("visibilitychange", function() {
if (!document.hidden) {
// Draw the content of the watch
drawWatchContent();
}
});
}
/**
* Initiates the application
* @private
*/
function init() {
setDefaultVariables();
setDefaultEvents();
// Draw the basic layout and the content of the watch at the beginning
drawWatchLayout();
drawWatchContent();
// Update the content of the watch every second
setInterval(function() {
drawWatchContent();
updateCalendar(60000);
}, 1000);
}
window.onload = init;
}());