Il ciclo

Un pannello definisce view(state) e, facoltativamente, initial(), on_open(state) e on_action(action, state). Clink chiama initial() una volta per lo stato iniziale, on_open ogni volta che il pannello compare, poi view(state) per costruire l'interfaccia. Un controllo inserisce testo dove stai scrivendo, imposta nuovo stato, oppure indica un'azione che on_action gestisce, e la vista viene ricostruita.

def initial():
    return {"count": 0, "step": 1}

def view(state):
    return vstack([
        text(f"{state['count']}", size=34, weight="bold", align="center"),
        segmented(["1", "5", "10"], value=str(state["step"]), action="step"),
        hstack([
            button("−", "bump", value=-1),
            button("+", "bump", value=1, style="primary"),
        ]),
        button("Type it", "type", icon="keyboard"),
    ])

def on_action(action, value, state):
    if action == "bump":
        state["count"] = state["count"] + value * state["step"]
    elif action == "step":
        state["step"] = int(value)
    elif action == "type":
        insert(str(state["count"]))
        close()
    return state
Il pannello di partenza, così come lo crea il pulsante Nuovo pannello dell'editor.

Calcolatrici, bacheche di snippet, selettori: i tuoi pannelli compaiono dietro il pulsante pannelli della tastiera.

Costruttori

view(state) restituisce nodi creati da queste 19 funzioni. Annidale liberamente: pile e griglie accettano un elenco di figli.

CostruttoreCosa disegna
vstack(children, spacing=6, align="leading")Impila i figli verso il basso.
hstack(children, spacing=6, align="center")Impila i figli in orizzontale.
grid(children, columns=4, spacing=6)Distribuisce i figli in colonne uguali.
wrap(children, spacing=6)Dispone i suoi elementi in larghezza e va a capo alla riga successiva.
scroll(children, spacing=6)Un'area a scorrimento propria, per un elenco più lungo del pannello.
card(children, padding=10, color="")Raggruppa i suoi elementi su una superficie, con spazio attorno.
spacer(size=0)Spinge quello che segue fino in fondo.
divider()Una linea sottile tra le righe.
text(s, size=17, weight="regular", color="", align="leading", lines=0, mono=False)Una riga di testo. weight accetta regular, medium, semibold, bold, heavy, light o thin; align accetta leading, center o trailing; lines limita quante righe occupa; color accetta un nome di colore o #RRGGBB.
icon(name, size=20, color="")Un SF Symbol, indicato per nome.
badge(s, color="")Una parola breve in una capsula colorata.
progress(value, total=1, label="")Una barra riempita fino a value su total.
button(label, action="", value=None, insert="", set=None, style="plain", icon="", enabled=True)Un pulsante. insert scrive il suo testo in ciò che stai scrivendo, set unisce chiavi nello stato e action indica un gestore per on_action. style accetta plain, primary, tinted, quiet o destructive.
row(title, subtitle="", detail="", icon="", action="", value=None, insert="")Una riga toccabile: un titolo, una seconda riga, un'icona e un dettaglio a destra.
toggle(label, on=False, key="", action="")Un interruttore. key scrive True o False in quella chiave di stato.
slider(value, min=0, max=100, step=1, label="", key="", action="")Un cursore fra min e max. key scrive la posizione in quella chiave di stato.
stepper(value, min=0, max=100, step=1, label="", key="", action="")Un valore con − e + accanto, fra min e max.
segmented(options, value=None, key="", action="")Una scelta da un elenco. key scrive l'opzione scelta in quella chiave di stato.
field(key, placeholder="", action="", submit="")Una casella di testo legata a state[key]. Toccandola i tasti scrivono in quella chiave; submit indica il gestore che Invio esegue.

Una semplice stringa vale ovunque valga un nodo: viene disegnata come testo nella dimensione predefinita.

Rispondere a un tocco

Un controllo che deve calcolare qualcosa indica un'action invece di portare un set fisso. Clink chiama allora on_action(action, state), oppure on_action(action, value, state) quando serve il valore che il controllo porta con sé. Lo stato è un normale dizionario: puoi modificarlo sul posto senza restituire nulla, o restituirne uno nuovo.

def initial():
    return {"items": [], "draft": ""}

def view(state):
    return vstack([
        field("draft", placeholder="Add one…", submit="add"),
        scroll([row(item, action="use", value=item) for item in state["items"]]),
    ])

def on_action(action, value, state):
    if action == "add" and value:
        state["items"].append(value)
        state["draft"] = ""
    elif action == "use":
        insert(value)
        close()
    return state
Un elenco a cui aggiungi e da cui inserisci con un tocco.

on_open(state) viene eseguita ogni volta che il pannello compare: è lì che un pannello parte da quello che stai scrivendo.

Chiedere alla tastiera

Da on_action e on_open un pannello può chiedere alla tastiera cose che un valore di ritorno non sa esprimere. Ogni chiamata viene annotata e applicata dopo che la tua funzione è terminata, così un pannello non modifica mai il campo mentre la sua vista viene costruita.

Comandi

  • insert()
  • backspace()
  • delete_word()
  • replace()
  • move_cursor()
  • copy()
  • close()
  • haptic()
  • toast()
def on_action(action, state):
    if action == "quote":
        word = context()["word"]
        replace(len(word), "“" + word + "”")
        haptic("light")
    return state
Sostituire la parola al cursore con la stessa fra virgolette.

context() legge quello che sta attorno al cursore: before, selected, after, word, clipboard, locale, language, full_access e time. È un’istantanea presa all’inizio della chiamata, quindi non può cambiarti sotto a metà del rendering.

Lo stato

Lo stato è un normale dizionario e contiene tutto ciò che uno script sa costruire: numeri, stringhe, booleani, None, e liste e dizionari di questi. Ti viene restituito a ogni chiamata, quindi una lista a cui hai aggiunto con un tocco c'è ancora al tocco dopo.

def initial():
    return {"name": ""}

def view(state):
    return vstack([
        field("name", placeholder="Who?"),
        button("Greet", insert="Hi " + state["name"] + "!", style="primary"),
    ])
Un campo scrive direttamente nella chiave di stato che gli indichi.

Ricorda lo stato conserva il contenuto del pannello tra un'apertura e l'altra, e tra le sessioni della tastiera. Lascialo spento per una calcolatrice, accendilo per un elenco.

Lo stato vive finché la tastiera è sullo schermo, e più a lungo quando il pannello ricorda. Un pannello può leggere il testo attorno al cursore con context(); nient'altro su di te.

Limiti

Una tastiera riceve una frazione della memoria di un'app, quindi i pannelli sono limitati anziché considerati affidabili. Ogni rendering ha 2.000.000 passi di interprete, e un ciclo impazzito finisce con un errore a schermo invece che con una tastiera che smette di rispondere.

Un pannello che arriva come file o da un repository viene controllato prima di essere salvato. Deve stare sotto 48.000 byte e 1200 righe, deve definire def view(, ogni import deve nominare uno degli spazi dei nomi isolati, e questi frammenti vengono rifiutati senz'altro:

Rifiutato in un pannello condiviso

  • __
  • exec(
  • eval(
  • open(
  • compile(

Importabile in un pannello condiviso

  • json
  • math
  • random
  • re
  • sys
  • time

I pannelli che scrivi nell'app non sono soggetti a quell'elenco. A fermare un ciclo impazzito resta allora solo il budget di passi: lasciagli una via d'uscita.

Posizionamento

Assegna a ogni pannello un proprio pulsante nel selettore, invece di annidarli tutti dietro un unico pulsante Pannelli. I singoli pannelli possono sovrascrivere questa impostazione nel proprio editor.

Predefinito segue quell'interruttore, Indipendente prende sempre un pulsante suo e Raggruppato si annida sempre.

Scriverne uno

  1. Apri Pannelli personalizzati in Clink e tocca Nuovo pannello.
  2. Scrivi lo script. Accanto gira un'anteprima del pannello vero e gli errori compaiono mentre scrivi.
  3. Salva, attiva il pannello, poi apri il pulsante dei pannelli sulla tastiera.

Pannello di condivisione crea un file .clinkpanel, che è JSON. Riaprendolo in Clink viene salvato con un id nuovo, quindi importare due volte lo stesso pannello non sovrascrive mai il primo.

Creatore ›
Scarica dall’App Store