shell

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: BSD-3-Clause Imports: 9 Imported by: 0

Documentation

Overview

Package shell holds the pure composition/model logic of the desktop shell: the launchable-app index, MIME "open with" resolution, the categorized application-menu model, the directory listing model and the thumbnail cache-key derivation. None of it touches a rendering surface, so every branch is unit-coverable against temp-dir fixtures; the render package turns these models into go-widgets widgets.

Index

Constants

View Source
const MimeDirectory = "inode/directory"

MimeDirectory is the MIME type the shell assigns to directory entries.

Variables

This section is empty.

Functions

func Thumbnailable

func Thumbnailable(it FileItem) bool

Thumbnailable reports whether a file item should be given an image preview: a regular file whose classified MIME type is an image/* type. Directories, unclassified items and non-image files are not thumbnailed.

Types

type App

type App struct {
	ID          string
	Name        string
	GenericName string
	Comment     string
	Icon        string
	Exec        string
	Categories  []string
	Keywords    []string
	Terminal    bool
	// contains filtered or unexported fields
}

App is one launchable application, distilled from a desktop entry into the fields a dock / launcher needs. The originating entry is retained so the launcher can expand its Exec line at click time.

func (App) Entry

func (a App) Entry() *desktopentry.Entry

Entry returns the desktop entry this App was built from (nil for an App that was not derived from one). The launcher passes it to desktopentry.ExpandExec.

func (App) Label

func (a App) Label() string

Label is the user-visible name, falling back to the desktop-file id when the entry carries no Name.

type AppIndex

type AppIndex struct {
	// contains filtered or unexported fields
}

AppIndex is a sorted, de-duplicated, searchable set of launchable apps.

func NewAppIndex

func NewAppIndex(entries []*desktopentry.Entry) *AppIndex

NewAppIndex builds an index from scanned desktop entries. Non-launchable entries (wrong Type, no Exec) are dropped; the first entry seen for a given non-empty id wins (desktopentry.Scan already applies XDG directory precedence, so "first" means "highest priority"). Apps are ordered case-insensitively by their display label.

func (*AppIndex) All

func (x *AppIndex) All() []App

All returns a copy of the indexed apps in order.

func (*AppIndex) At

func (x *AppIndex) At(i int) App

At returns the app at index i.

func (*AppIndex) Len

func (x *AppIndex) Len() int

Len is the number of indexed apps.

func (*AppIndex) Search

func (x *AppIndex) Search(query string) []App

Search returns the apps matching query in index order. A blank (or whitespace-only) query returns every app.

type AppSource added in v0.4.0

type AppSource interface {
	// Apps is the sorted, de-duplicated, searchable launchable-app index that
	// feeds the dock and launcher.
	Apps() *AppIndex
	// Menu is the flattened, ordered application menu.
	Menu() *MenuModel
	// Dir is the current directory listing, already MIME-classified, that
	// feeds the file grid. It may be nil when no directory is available.
	Dir() *Dir
	// Resolve answers the "open with" query for a bare file name plus optional
	// leading content bytes: the classified MIME type, its default application
	// and the ordered candidate applications.
	Resolve(name string, content []byte) OpenWith
	// IconBytes returns the encoded image bytes (PNG/JPEG/GIF) for an icon
	// referenced by theme name (e.g. "web-browser") or by absolute path (e.g.
	// a thumbnail), and ok=false when it cannot be resolved. The render layer
	// decodes the bytes into a go-widgets Image (falling back to a placeholder
	// swatch on ok=false), so this is the single icon-pixel seam a source must
	// satisfy — no source touches the toolkit.
	IconBytes(name string) ([]byte, bool)
	// ThumbKey returns the IconBytes key of a file item's thumbnail — an
	// absolute cache path for the native source, a virtual asset name for the
	// embedded one — or "" when the item is not thumbnailed.
	ThumbKey(it FileItem) string
}

AppSource is the data source behind the desktop shell: everything the UI needs to render a populated desktop, abstracted away from where it comes from. It supplies the launchable-app index, the categorized application menu, the current directory listing (already MIME-classified), the "open with" resolution for a file, the encoded image bytes for an icon (by theme name or absolute path), and — for a file item — the icon-loader key of its thumbnail (or "" when it has none).

The two implementations live in github.com/go-widgets/desktop/source:

  • the native xdgSource scans a real XDG filesystem (desktopentry.Scan + icontheme + mime/mimeapps + menu.Load + go-thumbnail), exactly the behavior the shell has always had; and
  • the embeddedSource serves a curated set from an embed.FS, so the shell renders a real, populated desktop in the browser (js/wasm), where no real filesystem exists.

Both drive the identical shell/render composition logic — the whole point of the seam — so a Scene built from either is indistinguishable to the toolkit.

type Category

type Category struct {
	Name string
	Icon string
	Apps []App
}

Category is one branch of the application menu: a user-visible directory name (plus its icon) and the launchable apps allocated to it.

type Dir

type Dir struct {
	Path  string
	Items []FileItem
}

Dir is a listed directory: its path and its items, directories first then files, each group ordered case-insensitively by name.

func ListDir

func ListDir(path string) (*Dir, error)

ListDir lists path into a Dir. It does not classify MIME types (call Classify for that); a read failure (missing / unreadable directory) is returned as an error.

func (*Dir) Classify

func (d *Dir) Classify(r *Resolver)

Classify fills each item's Mime using r: directories get MimeDirectory, regular files are classified by name+content. A file that cannot be resolved (e.g. it became unreadable) is left with an empty Mime rather than aborting the whole listing.

type FileItem

type FileItem struct {
	Name  string
	Path  string
	IsDir bool
	Mime  string
}

FileItem is one entry of a listed directory.

type MenuModel struct {
	Categories []Category
}

MenuModel is the desktop application menu flattened into an ordered list of non-empty categories, ready to render as a go-widgets Menu / MenuBar. Nested submenus are walked depth-first, so a category appears once per menu node that carries apps, in menu (layout) order.

func NewMenuModel

func NewMenuModel(tree *menu.Tree) *MenuModel

NewMenuModel flattens a resolved menu.Tree. A nil tree (or a tree with a nil Root) yields an empty model. Only menu nodes that actually contain apps become categories; a purely structural submenu with no direct apps is skipped but still descended into.

func (m *MenuModel) Len() int

Len is the number of non-empty categories.

type OpenWith

type OpenWith struct {
	MimeType   string
	Default    App
	HasDefault bool
	Candidates []App
}

OpenWith is the resolved "open with" answer for a path or MIME type: the classified MIME type, the default application (if any) and the ordered list of candidate applications.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver answers MIME classification and application-association queries by combining a shared MIME-info database with a mimeapps.list resolver.

func NewResolver

func NewResolver(db *mime.Database, apps *mimeapps.Resolver) *Resolver

NewResolver wires a MIME database and an application-association resolver into a Resolver.

func (*Resolver) ResolveName

func (r *Resolver) ResolveName(name string, content []byte) OpenWith

ResolveName classifies a bare name plus optional content bytes and resolves the associated applications. It performs no I/O, so it is the pure seam the path-based helper builds on.

func (*Resolver) ResolvePath

func (r *Resolver) ResolvePath(path string) (OpenWith, error)

ResolvePath classifies path by both name and content and resolves its associated applications. Directories (and other non-regular paths) are classified by name only. A stat failure (e.g. the path does not exist) or a content-read failure is returned as an error.

type Thumbnailer

type Thumbnailer struct {
	// contains filtered or unexported fields
}

Thumbnailer derives the freedesktop Thumbnail Managing Standard cache keys and paths for a file grid. It delegates the URI canonicalization, MD5 hash and cache-path layout to github.com/go-thumbnail/thumbnail (the owner of that mechanism) and adds only the shell's policy: which items are thumbnailed and under which stable key.

func NewThumbnailer

func NewThumbnailer(size thumbnail.Size) *Thumbnailer

NewThumbnailer builds a Thumbnailer for the given standard thumbnail size.

func (*Thumbnailer) Key

func (t *Thumbnailer) Key(it FileItem) string

Key returns the stable cache key (the MD5 hash of the file's canonical file:// URI) for a thumbnailable item, or "" when the item is not thumbnailable. Two items with the same path always produce the same key.

func (*Thumbnailer) Path

func (t *Thumbnailer) Path(it FileItem) string

Path returns the on-disk cache path where the item's thumbnail lives (or would be generated), or "" for a non-thumbnailable item.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL