NSGo

Core concepts

Platform services

Alerts, the clipboard, files, photos, sharing, storage, speech, networking and the app's lifecycle.

Alerts and the clipboard

cx.ShowAlert shows the platform’s alert or action sheet. Its Actions come back by index, and a role draws the cancel and destructive buttons the platform’s way.

cx.ShowAlert(core.AlertConfig{
	Title:   "Delete the file?",
	Message: "This cannot be undone.",
	Actions: []core.AlertAction{
		{Label: "Cancel", Role: core.AlertCancel},
		{Label: "Delete", Role: core.AlertDestructive},
	},
}, func(index int) {
	if index == 1 {
		remove()
	}
})

SetClipboard writes text and SetClipboardImage an image. ReadClipboard, ReadClipboardImage and ReadClipboardFiles answer asynchronously, and HasClipboardText and HasClipboardImage read what the clipboard holds without a paste notice.

cx.ReadClipboard(func(text string) { pasted.Set(text) })
cx.SetClipboard("Hello")

cx.OpenURL opens a URL in the system’s browser or app, and core.CheckURL says what it refuses: no scheme, over 16 KiB, spaces, a web address without a host, and javascript:, data:, blob:, file:, about: and asset:.

if err := core.CheckURL(url); err == nil {
	cx.OpenURL(url, func(opened bool) {
		if !opened {
			status.Set("No app opens that link.")
		}
	})
}

cx.OpenFile opens a file the app has in the app associated with its type, and cx.Share shows the system’s share sheet for files, text or both. A core.SharedFile is a path, with the name and type the other app sees.

cx.Share(core.ShareOptions{
	Files: []core.SharedFile{{Path: path, Name: "Notes.txt"}},
	Text:  "A note from NSGo",
}, func(shown bool, err error) {})

Photos and files

cx.PickImages shows the system’s photo picker and answers with core.PickedFiles, whose bytes, name, type and pixel size the app reads. cx.TakePhoto shows the camera where the platform has one; cx.Env().CanTakePhoto says whether it does.

cx.PickImages(core.PickOptions{Limit: 1, MaxDimension: 2048}, func(files []core.PickedFile) {
	if len(files) == 1 {
		avatar.Set(files[0].Data)
	}
})

cx.PickFiles picks files of any type, cx.PickDirectories picks folders as an fs.FS, and cx.SaveFile saves a file or bytes through the system’s save dialog. cx.PickScreenColor picks a color anywhere on the screen where the platform allows it.

Storage

cx.Storage() is the app’s key-value storage, kept on the device and shared by every graph of the app. Reads are synchronous and read inside a computation subscribe it to changes; SetItem returns a core.StorageFullError past the quota (core.StorageQuota, 5 MiB by default).

store := cx.Storage()
if token, ok := store.GetItem("token"); ok {
	login(token)
}
store.SetItem("token", token)

store.Keys() lists the keys, RemoveItem deletes one and Clear empties the storage. cx.DataDir() and cx.CacheDir() give the app’s folders for files the key-value storage is too small for; a Scope.ProvideStorage gives a subtree a partition of its own.

Networking

Go’s own net/http makes requests on every target, with the system’s TLS and proxy settings. Signals belong to the engine’s goroutine, so a response from another goroutine reaches them through cx.Post.

go func() {
	resp, err := http.Get("https://api.example.com/items")
	if err != nil {
		cx.Post(func() { errText.Set(err.Error()) })
		return
	}
	defer resp.Body.Close()
	var items []Item
	if err := json.NewDecoder(resp.Body).Decode(&items); err != nil {
		cx.Post(func() { errText.Set(err.Error()) })
		return
	}
	cx.Post(func() { list.Set(items) })
}()

cx.Post runs its function on the graph’s goroutine, where signals may be set. On Android the manifest asks for the internet permission, and image downloads cache themselves on disk.

Speech and the lifecycle

cx.StartSpeech recognizes speech with the system’s recognizer where cx.Env().CanRecognizeSpeech() says it exists, and answers with the transcript as it changes.

session, err := cx.StartSpeech(core.SpeechOptions{
	Lang:    "en-US",
	Interim: true,
	OnResult: func(text string, final bool) {
		transcript.Set(text)
	},
})
if err == nil {
	defer session.Stop()
}

cx.Env().Lifecycle() says whether the app is active, inactive or in the background, and cx.OnExit runs as it quits. cx.SetAppearance forces light or dark, cx.SetLocale chooses the language, cx.OnKey binds a keyboard shortcut, cx.RegisterHotKey binds one while any app is frontmost, and cx.OnOpenFiles hears the documents a macOS app opens.

cx.OnKey("mod+k", func() { palette.Set(true) })
cx.SetLocale("de")

Next

Edit this page on GitHub