8
8
*
9
9
* Displays a random xkcd comic in a widget.
10
10
*
11
- * It's a modified version of
11
+ * It's a <em>heavily</em> modified version of
12
12
* <a href="https://gist.github.com/rudotriton/9d11ce1101ff1269f56844871b3fd536">rudotriton's script</a>.
13
13
*/
14
14
@@ -17,22 +17,36 @@ const URL_PREFIX = 'https://xkcd.com/';
17
17
const URL_POSTFIX = 'info.0.json' ;
18
18
// For development, displays the widget if run from the Scriptable app.
19
19
const DEBUG = false ;
20
+ const IS_ONLINE = await checkIsOnline ( ) ;
20
21
21
- const [ image , title , imageURL ] = await getRandomComic ( ) ;
22
+ const comic = IS_ONLINE ? await getRandomComic ( ) : undefined ;
22
23
23
24
if ( config . runsInWidget ) {
24
25
// Create and show the widget on home screen.
25
- const widget = createWidget ( image , title , imageURL ) ;
26
+ const widget = createWidget ( comic ) ;
26
27
Script . setWidget ( widget ) ;
27
28
Script . complete ( ) ;
28
29
} else if ( DEBUG ) {
29
- const widget = createWidget ( image , title , imageURL ) ;
30
+ const widget = createWidget ( comic ) ;
30
31
await widget . presentLarge ( ) ;
31
32
} else {
32
- Safari . open ( imageURL ) ;
33
+ if ( IS_ONLINE && comic ?. xkcdURL ) {
34
+ Safari . open ( comic . xkcdURL ) ;
35
+ }
33
36
}
34
37
35
- /** @return {Array<Image, string, string> } Random comic data. */
38
+ /** @return {bool } Whether the device has internet access. */
39
+ async function checkIsOnline ( ) {
40
+ const request = new Request ( 'https://duckduckgo.com' ) ;
41
+ try {
42
+ await request . load ( ) ;
43
+ } catch ( exception ) {
44
+ return false ;
45
+ }
46
+ return true ;
47
+ }
48
+
49
+ /** @return {object } Data of the randomised comic. */
36
50
async function getRandomComic ( ) {
37
51
const randomComicNumber = await getRandomComicNumber ( ) ;
38
52
const randomComicURL = URL_PREFIX + randomComicNumber + '/' + URL_POSTFIX ;
@@ -42,7 +56,12 @@ async function getRandomComic() {
42
56
const imageRequest = await new Request ( imageURL ) ;
43
57
const image = await imageRequest . loadImage ( ) ;
44
58
45
- return [ image , title , imageURL ] ;
59
+ return {
60
+ image,
61
+ title,
62
+ imageURL,
63
+ xkcdURL : URL_PREFIX + randomComicNumber ,
64
+ } ;
46
65
}
47
66
48
67
/** @return {number } Random comic number. */
@@ -64,31 +83,37 @@ function getRandomNumber(min, max) {
64
83
}
65
84
66
85
/**
67
- * @param {Image } image The image to display.
68
- * @param {string } title Title of the widget.
69
- * @param {string } widgetURL URL for the widget to open.
86
+ * Creates a {@link ListWidget} displaying the given comic. If the device is offline, creates an
87
+ * empty "You're offline" widget.
88
+ * <p>
89
+ * NOTE: The layout uses two horizontal stacks to be able to centre the title and the image. For
90
+ * some reason, `WidgetText#centerAlignText()` didn't work on home screen.
91
+ * @param {object } comic Data of a randomised comic.
70
92
* @return {ListWidget } The newly created widget instance.
71
93
*/
72
- function createWidget ( image , title , widgetURL ) {
94
+ function createWidget ( comic ) {
73
95
const widget = new ListWidget ( ) ;
74
- widget . url = widgetURL ;
75
- widget . refreshAfterDate = getDateIn30Minutes ( ) ;
76
96
77
- // The layout uses two horizontal stacks to be able to centre the title and the image. For some
78
- // reason, `WidgetTexts#centerAlignText()` didn't work on home screen.
79
97
/** @type {WidgetStack } */
80
98
const titleStack = widget . addStack ( ) ;
81
99
titleStack . addSpacer ( null ) ;
82
100
/** @type {WidgetText } */
83
- const titleStackText = titleStack . addText ( title ) ;
101
+ const titleStackText = titleStack . addText (
102
+ IS_ONLINE && comic ?. title ? comic . title : "You're offline"
103
+ ) ;
84
104
titleStackText . font = Font . headline ( ) ;
85
105
titleStack . addSpacer ( null ) ;
86
106
87
- /** @type {WidgetStack } */
88
- const imageStack = widget . addStack ( ) ;
89
- imageStack . addSpacer ( null ) ;
90
- imageStack . addImage ( image ) ;
91
- imageStack . addSpacer ( null ) ;
107
+ if ( IS_ONLINE && comic ) {
108
+ /** @type {WidgetStack } */
109
+ const imageStack = widget . addStack ( ) ;
110
+ imageStack . addSpacer ( null ) ;
111
+ imageStack . addImage ( comic . image ) ;
112
+ imageStack . addSpacer ( null ) ;
113
+
114
+ widget . url = comic . xkcdURL ;
115
+ widget . refreshAfterDate = getDateIn30Minutes ( ) ;
116
+ }
92
117
93
118
return widget ;
94
119
}
0 commit comments