Skip to content

Instantly share code, notes, and snippets.

@icsAT
Created June 5, 2021 13:54
Show Gist options
  • Save icsAT/5f4136d53e379a7a343e65ad59f39a44 to your computer and use it in GitHub Desktop.
Save icsAT/5f4136d53e379a7a343e65ad59f39a44 to your computer and use it in GitHub Desktop.
Einfaches Skript zur Darstellung der Uhrzeit in Textform in einem Scriptable Widget.
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: light-gray; icon-glyph: magic;
// Quelle: https://gist.github.com/icsAT
// Version 0.80 vom 05.06.2021
// Die Idee zu dieser Widget Germanisierung stammt aus der Facebook Gruppe "Scriptable ios"
// von Oliver Shmith, der jemanden gesucht hat, der ein englischsprechiges Widget auf
// deutsch umbaut.
// Die Version 2 highlighted einzelne Buchstaben, statt ganze Worte. Dadurch ist die Optik harmonischer.
// Als Basis diente das Skript "WorldClockWidget" von Linda Zheng.
// Das Original findet man hier:
// https://github.com/yaylinda/scriptable/blob/main/WordClockWidget.js
/*=========================================================
* WIDGET CONFIGURATIONS
========================================================*/
const WIDGET_CONFIGURATIONS = {
// If this is true, it opens a prompt to select a
// background image from the photo gallery,
// when the widget is run from the Scriptable app
useBackgroundImage: true,
// If useBackgroundImage is set to false, this background
// color gradient will be use. Feel free to set to your
// own colors
backgroundColor: [
new Color("#29323c"),
new Color("#1c1c1c")
],
// The font to use for the words in the word clock
font: 'Menlo-Bold',
// The font size to use for the words in the word clock
fontSize: 12,
// The color to use for the "highlighted" words.
// The "highlighted" words tells the time
textColorHighlighted: Color.white(),
// The color of the highlighted text shadow
textShadowHighlighted: Color.cyan(),
// The radius of the highlighted text shadow
textShadowHighlightedRadius: 3,
// The color of the words that are NOT highlighted
textColorBackground: Color.lightGray(),
// The opacity of the non-highlighted words
// 1 -> opaque; 0 -> transparent
textAlphaBackground: 0.5,
// The spacing between the lines of words of the clock
spacingBetweenLines: 3,
// The spacing between each individual word, within the
// same line
spacingBetweenWords: 2,
}
/*=========================================================
* WIDGET SET UP / PRESENTATION
========================================================*/
/**
* The words to display for the clock. If you want to use
* other words, make sure to update getHighlightedWords()
* accordingly.
*/
const TIME_WORDS_MATRIX = [
['E', 'S', 'T', 'I', 'S', 'T', 'I', 'M', 'E', 'I', 'N', 'E'],
['V', 'I', 'E', 'R', 'T', 'E', 'L', 'A', 'Z', 'E', 'H', 'N'],
['Z', 'W', 'A', 'N', 'Z', 'I', 'G', 'F', 'Ü', 'N', 'F', 'N'],
['N', 'A', 'C', 'H', 'V', 'O', 'R', 'D', 'H', 'A', 'L', 'B'],
['D', 'A', 'T', 'Z', 'W', 'Ö', 'L', 'F', 'E', 'I', 'N', 'S'],
['Z', 'W', 'E', 'I', 'D', 'R', 'E', 'I', 'V', 'I', 'E', 'R'],
['F', 'Ü', 'N', 'F', 'S', 'E', 'C', 'H', 'S', 'E', 'L', 'F'],
['S', 'I', 'E', 'B', 'E', 'N', 'E', 'A', 'C', 'H', 'T', 'T'],
['N', 'E', 'U', 'N', 'I', 'Z', 'E', 'H', 'N', 'U', 'H', 'R'],
];
const widget = new ListWidget();
await setBackground(widget, WIDGET_CONFIGURATIONS);
drawWidget(widget, WIDGET_CONFIGURATIONS);
if (config.runsInWidget) {
Script.setWidget(widget);
Script.complete();
} else {
Script.setWidget(widget);
widget.presentSmall();
Script.complete();
}
/*=========================================================
* FUNCTIONS
========================================================*/
/**
* Main widget rendering function.
*
* Lays out the widget as a vertical list of stacks,
* containing texts.
*/
function drawWidget(widget, {
font,
fontSize,
textColorHighlighted,
textShadowHighlighted,
textShadowHighlightedRadius,
textColorBackground,
textAlphaBackground,
spacingBetweenLines,
spacingBetweenWords,
}) {
const mainStack = widget.addStack();
mainStack.layoutVertically();
mainStack.spacing = spacingBetweenLines;
const highlightedWords = getHighlightedWords();
for (let i = 0; i < TIME_WORDS_MATRIX.length; i++) {
const numWords = TIME_WORDS_MATRIX[i].length;
const textStack = mainStack.addStack();
textStack.layoutHorizontally();
textStack.spacing = spacingBetweenWords;
for (let j = 0; j < numWords; j++) {
const text = textStack.addText(TIME_WORDS_MATRIX[i][j]);
text.font = new Font(font, fontSize);
if (highlightedWords[i] && highlightedWords[i][j]) {
text.textColor = textColorHighlighted;
text.shadowColor = textShadowHighlighted;
text.shadowRadius = textShadowHighlightedRadius;
} else {
text.textColor = textColorBackground;
text.alpha = textAlphaBackground;
}
}
}
}
/**
* Based on the input time, returns an array of arrays of
* which "time" words should be highlighted.
*
* This is used as a look-up when adding texts to the
* stack.
*/
function getHighlightedWords() {
// The dimensions of this should match the dimensions of
// TIME_WORDS_MATRIX
const defaultHighlights = [
[true, true, false, true, true, true, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
[false, false, false, false, false, false, false, false, false, false, false, false],
];
const date = new Date();
let hour = date.getHours();
const minute = date.getMinutes();
if (minute >= 25) {
// increment hour
hour = hour + 1;
}
if (minute >= 0 && minute < 5) {
// highlight "uhr"
defaultHighlights[8][9] = true;
defaultHighlights[8][10] = true;
defaultHighlights[8][11] = true;
} else if (minute >= 5 && minute < 10) {
// highlight "fünf"
defaultHighlights[2][7] = true;
defaultHighlights[2][8] = true;
defaultHighlights[2][9] = true;
defaultHighlights[2][10] = true;
// highlight "nach"
defaultHighlights[3][0] = true;
defaultHighlights[3][1] = true;
defaultHighlights[3][2] = true;
defaultHighlights[3][3] = true;
} else if (minute >= 10 && minute < 15) {
// highlight "zehn"
defaultHighlights[1][8] = true;
defaultHighlights[1][9] = true;
defaultHighlights[1][10] = true;
defaultHighlights[1][11] = true;
/// highlight "nach"
defaultHighlights[3][0] = true;
defaultHighlights[3][1] = true;
defaultHighlights[3][2] = true;
defaultHighlights[3][3] = true;
} else if (minute >= 15 && minute < 20) {
// highlight "virtel"
defaultHighlights[1][0] = true;
defaultHighlights[1][1] = true;
defaultHighlights[1][2] = true;
defaultHighlights[1][3] = true;
defaultHighlights[1][4] = true;
defaultHighlights[1][5] = true;
defaultHighlights[1][6] = true;
// highlight "nach"
defaultHighlights[3][0] = true;
defaultHighlights[3][1] = true;
defaultHighlights[3][2] = true;
defaultHighlights[3][3] = true;
} else if (minute >= 20 && minute < 25) {
// highlight "zwanzig"
defaultHighlights[2][0] = true;
defaultHighlights[2][1] = true;
defaultHighlights[2][2] = true;
defaultHighlights[2][3] = true;
defaultHighlights[2][4] = true;
defaultHighlights[2][5] = true;
defaultHighlights[2][6] = true;
// highlight "nach"
defaultHighlights[3][0] = true;
defaultHighlights[3][1] = true;
defaultHighlights[3][2] = true;
defaultHighlights[3][3] = true;
} else if (minute >= 25 && minute < 30) {
// highlight "fünf"
defaultHighlights[2][7] = true;
defaultHighlights[2][8] = true;
defaultHighlights[2][9] = true;
defaultHighlights[2][10] = true;
// highlight "vor"
defaultHighlights[3][4] = true;
defaultHighlights[3][5] = true;
defaultHighlights[3][6] = true;
// highlight "halb"
defaultHighlights[3][8] = true;
defaultHighlights[3][9] = true;
defaultHighlights[3][10] = true;
defaultHighlights[3][11] = true;
} else if (minute >= 30 && minute < 35) {
// highlight "halb"
defaultHighlights[3][8] = true;
defaultHighlights[3][9] = true;
defaultHighlights[3][10] = true;
defaultHighlights[3][11] = true;
} else if (minute >= 35 && minute < 40) {
// highlight "fünf"
defaultHighlights[2][7] = true;
defaultHighlights[2][8] = true;
defaultHighlights[2][9] = true;
defaultHighlights[2][10] = true;
// highlight "nach"
defaultHighlights[3][0] = true;
defaultHighlights[3][1] = true;
defaultHighlights[3][2] = true;
defaultHighlights[3][3] = true;
// highlight "halb"
defaultHighlights[3][8] = true;
defaultHighlights[3][9] = true;
defaultHighlights[3][10] = true;
defaultHighlights[3][11] = true;
} else if (minute >= 40 && minute < 45) {
// highlight "zwanzig"
defaultHighlights[2][0] = true;
defaultHighlights[2][1] = true;
defaultHighlights[2][2] = true;
defaultHighlights[2][3] = true;
defaultHighlights[2][4] = true;
defaultHighlights[2][5] = true;
defaultHighlights[2][6] = true;
// highlight "vor"
defaultHighlights[3][4] = true;
defaultHighlights[3][5] = true;
defaultHighlights[3][6] = true;
} else if (minute >= 45 && minute < 50) {
// highlight "virtel"
defaultHighlights[1][0] = true;
defaultHighlights[1][1] = true;
defaultHighlights[1][2] = true;
defaultHighlights[1][3] = true;
defaultHighlights[1][4] = true;
defaultHighlights[1][5] = true;
defaultHighlights[1][6] = true;
// highlight "vor"
defaultHighlights[3][4] = true;
defaultHighlights[3][5] = true;
defaultHighlights[3][6] = true;
} else if (minute >= 50 && minute < 55) {
// highlight "zehn"
defaultHighlights[1][8] = true;
defaultHighlights[1][9] = true;
defaultHighlights[1][10] = true;
defaultHighlights[1][11] = true;
// highlight "vor"
defaultHighlights[3][4] = true;
defaultHighlights[3][5] = true;
defaultHighlights[3][6] = true;
} else if (minute >= 55) {
// highlight "fünf"
defaultHighlights[2][7] = true;
defaultHighlights[2][8] = true;
defaultHighlights[2][9] = true;
defaultHighlights[2][10] = true;
// highlight "vor"
defaultHighlights[3][4] = true;
defaultHighlights[3][5] = true;
defaultHighlights[3][6] = true;
}
if (hour > 12) {
hour = hour - 12;
}
if (hour === 1) {
defaultHighlights[4][8] = true;
defaultHighlights[4][9] = true;
defaultHighlights[4][10] = true;
if (minute >= 5) {
defaultHighlights[4][11] = true;
}
} else if (hour === 2) {
defaultHighlights[5][0] = true;
defaultHighlights[5][1] = true;
defaultHighlights[5][2] = true;
defaultHighlights[5][3] = true;
} else if (hour === 3) {
defaultHighlights[5][4] = true;
defaultHighlights[5][5] = true;
defaultHighlights[5][6] = true;
defaultHighlights[5][7] = true;
} else if (hour === 4) {
defaultHighlights[5][8] = true;
defaultHighlights[5][9] = true;
defaultHighlights[5][10] = true;
defaultHighlights[5][11] = true;
} else if (hour === 5) {
defaultHighlights[6][0] = true;
defaultHighlights[6][1] = true;
defaultHighlights[6][2] = true;
defaultHighlights[6][3] = true;
} else if (hour === 6) {
defaultHighlights[6][4] = true;
defaultHighlights[6][5] = true;
defaultHighlights[6][6] = true;
defaultHighlights[6][7] = true;
} else if (hour === 7) {
defaultHighlights[7][0] = true;
defaultHighlights[7][1] = true;
defaultHighlights[7][2] = true;
defaultHighlights[7][3] = true;
defaultHighlights[7][4] = true;
defaultHighlights[7][5] = true;
} else if (hour === 8) {
defaultHighlights[7][7] = true;
defaultHighlights[7][8] = true;
defaultHighlights[7][9] = true;
defaultHighlights[7][10] = true;
} else if (hour === 9) {
defaultHighlights[8][0] = true;
defaultHighlights[8][1] = true;
defaultHighlights[8][2] = true;
defaultHighlights[8][3] = true;
} else if (hour === 10) {
defaultHighlights[8][5] = true;
defaultHighlights[8][6] = true;
defaultHighlights[8][7] = true;
defaultHighlights[8][8] = true;
} else if (hour === 11) {
defaultHighlights[6][9] = true;
defaultHighlights[6][10] = true;
defaultHighlights[6][11] = true;
} else if (hour === 12) {
defaultHighlights[4][3] = true;
defaultHighlights[4][4] = true;
defaultHighlights[4][5] = true;
defaultHighlights[4][6] = true;
defaultHighlights[4][7] = true;
}
return defaultHighlights;
}
/**
* Sets the background on the widget.
*
* If the script/widget is running as a widget,
* set the background from the cache.
*
* If no background image is in the cache,
* default to the gray gradient.
*
* If running in the app, prompt the user to select a
* background image. Persist in cache.
*/
async function setBackground(widget, {
useBackgroundImage,
backgroundColor,
}) {
if (useBackgroundImage) {
// Determine if our image exists and when it was saved.
const files = FileManager.local();
const path = files.joinPath(
files.documentsDirectory(),
'word-clock-widget-background'
);
const exists = files.fileExists(path);
// If it exists and we're running in the widget,
// use photo from cache
// Or we're invoking the script to run FROM the widget
// with a widgetParameter
if (exists && config.runsInWidget
|| args.widgetParameter === 'callback') {
widget.backgroundImage = files.readImage(path);
// If it's missing when running in the widget,
// fallback to backgroundColor
} else if (!exists && config.runsInWidget) {
const bgColor = new LinearGradient();
bgColor.colors = backgroundColor;
bgColor.locations = [0.0, 1.0];
widget.backgroundGradient = bgColor;
// But if we're running in app, prompt the user for
// the image.
} else if (config.runsInApp) {
const img = await Photos.fromLibrary();
widget.backgroundImage = img;
files.writeImage(path, img);
}
} else {
const bgColor = new LinearGradient();
bgColor.colors = backgroundColor;
bgColor.locations = [0.0, 1.0];
widget.backgroundGradient = bgColor;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment