One weekday evening, near dinner time, I opened the nuggets and found a cute iOS desktop component that could be written in Javascript! 👇 Use Scriptable to create your own iPhone widget
Hello World learned, however, that while writing the components they wanted, they still knew very little about them, and the official documentation was rudimentary. Therefore, I want to share what I understand and gain, so that you can better write your own ideal components by hand.
(It is recommended to go to the above article to understand the usage.)
The container
Containers in Scriptable are equivalent to Html tag elements. Contents to be displayed must be placed in containers to be presented, mainly including the following:
- ListWidget: The most basic, outermost container, equivalent to
<body>
- WidgetStack: a block equivalent to
<div>
/<span>
- WidgetText: Text container
- WidgetSpacer: Empty line element, elastic scaling
- WidgetImage: Image container
- WidgetDate: date container, automatically refreshed (other contents in Scriptable are not refreshed in real time, so date and time contents need to be placed in a special container)
layout
ListWidget
As the base container for the entire component, there are three sizes available:
To determine whether to obtain the config. WidgetFamily
WidgetStack
Create a new one using the addStack() method of the ListWidget. Create a “row” directly from the ListWidget, and then create a “column” row from the ListWidget, as follows:
const widget = new ListWidget()
const row = widget.addStack()
const cell = row.addStack()
Copy the code
A small example of a table layout with 8 rows and 10 columns:
const widget = new ListWidget()
widget.spacing = 2 // Make a bit of padding
for (let i=0; i<8; i++) {
const row = widget.addStack()
row.spacing = 2 // Make a bit of padding
for (let j=0; j<10; j++) {
const cell = row.addStack()
cell.size = new Size(12.12)
cell.cornerRadius = 100 // border-radius: 100%
cell.backgroundColor = new Color(`#ff${i}6${j}6 `) // Change the color to I and j}}Copy the code
WidgetSpacer
Used to create empty elements such as widget.addspacer (len: number) and row.addspacer (len). When len = 0, it is useful for creating elastic Spaces. For example, we could insert WdigetSpacer in the middle of each row in the table example above:
const widget = new ListWidget()
widget.spacing = 2 // Make a bit of padding
for (let i=0; i<8; i++) {
const row = widget.addStack()
row.spacing = 2 // Make a bit of padding
for (let j=0; j<10; j++) {
// ...
if (j === 4) {
row.addSpacer()
}
}
}
Copy the code
Development framework
The debugging process is very low-level and time-consuming if the code is written only on the IDE and then copied and pasted into Scriptable, so here is an interesting widget development framework:
It will connect PC to Scriptable, and then we can write code directly on VSCode. After saving, the code will be automatically synchronized to the mobile phone and run automatically. The specific operation method is clearly written in the author’s document, which is not repeated here.
Briefly say the analysis of its implementation ideas:
- Start the Node service on the PC, enter the server address (THE IP address of the PC) on the mobile terminal, and upload the file
POST
Brought the Node - Node end after the save to the local, record the file update time, use
child_process.exec
Open VSCode with system commands and open editing - The client
while(1)
The Node side compares the latest update time of the file with the record time, and sends the file to the client when it is updated - Finally, the client parses, updates the file, and executes
Here’s an interesting point: the client will await the request while(1) :
const _res = await _req.loadString()
Copy the code
The node response to the request is placed in a 1s setTimeout:
setTimeout(() = > {
// Determine the file time
const _time = fs.statSync(WIDGET_FILE).mtimeMs
if (_time === FILE_DATE) {
res.send("no").end()
return
}
/ / synchronize
res.sendFile(WIDGET_FILE)
console.log('[+] Sync to phone finished ')
FILE_DATE = _time
}, 1000)
Copy the code
Therefore, it is through the delayed response of the node side to achieve the effect of controlling the client while throttling.
Deficiencies and Expectations
- Single layout, unable to get container width and height (impossible to fit different screens)
- Background not transparent (opacity 0, result is black background)
- Update frequency cannot be set (can only be set later than default frequency…)
- Unable to update data-driven view (interface/local storage may be available)
The sample
Finally, click the list component of my website B, and you can directly jump to the corresponding video of the App of Website B: (The upper left corner is a local love-talk panel that is mixed in, and you can swipe your phone to have a look before dating…)
B station component source 👈
Components of other people’s homes 👈