assoc

package
v0.52.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package assoc decides which handler opens a kind of file and which draws its thumbnail (filex 0.50, docs/APP-PLUGINS.md → Default apps).

Every kind of file - its extension - has two CAPABILITIES, and each an ordered list of HANDLERS:

  • open: filex's own viewer ("builtin"), every app interface that opens the kind ("app:<app>/<view>", a `viewer` view) and, for the kinds it opens as a choice (OnlyOfficeOpens: `.csv`, filex 0.51), the document server ("onlyoffice") while OnlyOffice is configured;
  • thumbnail: the document server ("onlyoffice", for the office kinds it draws, while OnlyOffice is configured), filex's own drawer ("builtin", for the kinds it draws) and every app whose `thumbnails` block names the kind ("app:<app>").

The administrator's RULE for a kind and a capability reorders that list and switches handlers off; a kind with no rule keeps the default order. The person chooses only among the openers that are on (the explorer keeps that choice on the account); thumbnails are the administrator's alone.

⚠⚠ ONE rule for every caller. The thumbnail pipeline (which handler draws, and whether a picture is stale), the explorer's listing (which openers are offered) and the server's own refusal of an interface on a kind it was switched off for all read Chain - so "off" means the same thing everywhere.

Index

Constants

View Source
const (
	CapOpen      = "open"
	CapThumbnail = "thumbnail"
)

Capabilities.

View Source
const (
	DrawFailed   = "failed"
	DrawTimeout  = "timeout"
	DrawTooLarge = "too_large"
)

Draw error codes (DrawError.Code).

View Source
const Builtin = "builtin"

Builtin is filex's own handler: its viewer, or its thumbnail drawer.

View Source
const OnlyOffice = "onlyoffice"

OnlyOffice is the document server filex is configured with, as a handler of filex's own (not an app's):

  • thumbnail (filex 0.50): a picture of an office document's first page (docs/thumbnails.md → Office through OnlyOffice), for the kinds it draws while OnlyOffice is configured, first in their default order;
  • open (filex 0.51): ONLYOFFICE's spreadsheet editor, for the kinds whose opening is a choice between it and filex's own viewer (OnlyOfficeOpens, `.csv` only), first in their default order while OnlyOffice is configured (docs/ONLYOFFICE.md → CSV files).

⚠ The office kinds themselves (docx, xlsx, ...) are not opened through this chain: the document server is the only thing that opens them, there is nothing to choose.

Variables

This section is empty.

Functions

func AppOf

func AppOf(id string) string

AppOf is the app an app handler's id names ("" for builtin or a malformed id).

func ExtOf

func ExtOf(name string) string

ExtOf is the kind of a file name: its last extension, lower-case, no dot; "" for a name without one (or one that is only a dot-file's name).

func ExtsOfMime

func ExtsOfMime(m string) []string

ExtsOfMime is every known kind of a media type (exact) or a family (`image/*`), sorted. `*/*` names none: an app may not claim every kind.

func HandledKinds

func HandledKinds(open, thumb []AppHandler) map[string]bool

HandledKinds is every capability and kind an app's handlers cover, by KindKey.

func KindKey

func KindKey(capability, ext string) string

KindKey names one capability of one kind ("open .drawio").

func MimeOf

func MimeOf(ext string) string

MimeOf is the media type the screens give a kind ("" when unknown).

func NewKinds

func NewKinds(before, after map[string]bool) map[string]bool

NewKinds are the kinds in after that are not in before: what an upgrade adds.

func OnlyOfficeOpenKinds added in v0.51.0

func OnlyOfficeOpenKinds() []string

OnlyOfficeOpenKinds is the list OnlyOfficeOpens answers from, sorted.

func OnlyOfficeOpens added in v0.51.0

func OnlyOfficeOpens(ext string) bool

OnlyOfficeOpens reports whether the document server is an open handler of this kind (an extension, as ExtOf gives it).

func OpenID

func OpenID(app, view string) string

OpenID is an app view's handler id for the open capability.

func ThumbID

func ThumbID(app string) string

ThumbID is an app's handler id for the thumbnail capability.

func ValidCapability

func ValidCapability(c string) bool

ValidCapability reports whether c is a capability.

func ValidExt

func ValidExt(ext string) bool

ValidExt reports whether ext may name a kind.

func ValidID

func ValidID(capability, id string) bool

ValidID reports whether id is a handler id of the capability's shape.

Types

type AppHandler

type AppHandler struct {
	Handler
	Ext  []string
	Mime []string
}

AppHandler is an app's handler and the kinds it handles: extensions, and media types (exact, or a family like `image/*`).

func (AppHandler) Matches

func (a AppHandler) Matches(ext, mime string) bool

Matches reports whether the handler handles a file of this extension (as ExtOf gives it) or this media type.

type Chain

type Chain struct {
	On  []Handler
	Off []Handler
	// Custom: an administrator's rule decided this order (false: the default).
	Custom bool
}

Chain is the handlers of one kind and one capability: the ones that are on, in the order they are asked, and the ones switched off.

func (Chain) AllOff

func (c Chain) AllOff() bool

AllOff reports whether handlers exist for the kind and every one of them is switched off - as opposed to a kind nobody handles.

func (Chain) Has

func (c Chain) Has(id string) bool

Has reports whether the handler id is on in the chain.

func (Chain) Keys

func (c Chain) Keys() []string

Keys are the chain's handlers as a thumbnail row records them (Key).

type DrawError

type DrawError struct {
	App   string
	Code  string
	Limit int64
	Err   error
}

DrawError is why an app did not draw a file. Limit is the limit that was hit: bytes for too_large, milliseconds for timeout.

func AsDrawError

func AsDrawError(app string, err error) *DrawError

AsDrawError returns err as a *DrawError, or a failed one for any other error.

func (*DrawError) Error

func (e *DrawError) Error() string

func (*DrawError) Unwrap

func (e *DrawError) Unwrap() error

type DrawRequest

type DrawRequest struct {
	NodeID    int64
	StorageID int64
	Path      string
	Name      string
	Mime      string
	Size      int64
	Body      io.Reader
}

DrawRequest is one file an app is asked to draw. The app is handed Body, Name, Mime and Size; NodeID, StorageID and Path are for the host's own record (the audit row of a call that sent the file out) and never reach the app.

type ErrInvalid

type ErrInvalid struct{ Message string }

ErrInvalid is a rule a caller may not store; the message says why.

func (*ErrInvalid) Error

func (e *ErrInvalid) Error() string

type Handler

type Handler struct {
	// ID is "builtin", "app:<app>/<view>" (open) or "app:<app>" (thumbnail).
	ID string `json:"id"`
	// App and View name an app's handler; both empty for the built-in one.
	App  string `json:"app,omitempty"`
	View string `json:"view,omitempty"`
	// Version is the app's version: part of what a thumbnail records about who
	// drew it, so an upgrade makes its pictures stale.
	Version string `json:"version,omitempty"`
	// Label is the app's (or the view's) name, in its languages; empty for the
	// built-in handler, which every client names itself.
	Label wire.Text `json:"label,omitempty"`
}

Handler is one way to open, or to draw, a kind of file.

func Apply

func Apply(avail []Handler, r *Rule) (on, off []Handler)

Apply orders the available handlers (in their default order) by r: the ones r switches off are left out; the ones r names come first, in r's order; every other one follows in the default order. A nil rule is the default order. `off` is the handlers left out, in the default order.

⚠ A handler the rule does not name (an app installed after the rule was written) is ON, after the named ones: installing an app never needs the rule to be rewritten for it to work, and it never jumps the queue.

func DefaultOrder

func DefaultOrder(capability string, builtin bool, apps []Handler) []Handler

DefaultOrder is the order a kind's handlers are asked in until an administrator decides otherwise:

  • open: the apps first (in the order given: by app name, then each app's views in its manifest's order), filex's own viewer last - what 0.49 did, where an installed app opened its kind and *Open with* offered the rest;
  • thumbnail: filex's own drawer first (when it draws the kind), then the apps by name - an app is asked for what filex could not draw.

func OpenDefault added in v0.51.0

func OpenDefault(onlyoffice bool, apps []Handler) []Handler

OpenDefault is the open capability's default order: the document server first for a kind it opens as a choice while OnlyOffice is configured (onlyoffice: the product's default for a CSV is ONLYOFFICE's spreadsheet, filex 0.51), then DefaultOrder - the apps, filex's own viewer last.

func ThumbDefault

func ThumbDefault(onlyoffice, builtin bool, apps []Handler) []Handler

ThumbDefault is the thumbnail capability's default order: the document server first for a kind it draws (onlyoffice: a real page of an office document), then DefaultOrder - filex's own drawer when it draws the kind, then the apps by name.

func (Handler) IsApp

func (h Handler) IsApp() bool

IsApp reports whether h is an app's handler (not one of filex's own).

func (Handler) IsBuiltin

func (h Handler) IsBuiltin() bool

IsBuiltin reports whether h is filex's own handler.

func (Handler) IsOnlyOffice

func (h Handler) IsOnlyOffice() bool

IsOnlyOffice reports whether h is the document server (its thumbnail handler, or its editor for a kind it opens as a choice).

func (Handler) Key

func (h Handler) Key() string

Key is how a thumbnail row records the handler: the id, and an app's version (`app:pkglist@1.2.0`), so the same app in another version is a different handler for freshness.

type InstallKind

type InstallKind struct {
	Capability string `json:"capability"`
	Ext        string `json:"ext"`
	Mime       string `json:"mime,omitempty"`
	// Handler is the new app's handler for the kind.
	Handler Handler `json:"handler"`
	// Current are the handlers on for the kind now, in order.
	Current []Handler `json:"current"`
	// Default is where the app lands with no choice: first, or after the
	// others (a kind with a rule keeps its named handlers in front).
	Default Place `json:"default"`
}

InstallKind is one row of the install review's File types group: a kind the new app would open or draw thumbnails of, who handles it now, and where the app lands when the administrator chooses nothing.

func OnlyNewInstallKinds

func OnlyNewInstallKinds(rows []InstallKind, before map[string]bool) []InstallKind

OnlyNewInstallKinds keeps the File types rows whose kind the app did not handle before (before, by KindKey): an upgrade's review asks about those.

type Kind

type Kind struct {
	Ext       string  `json:"ext"`
	Mime      string  `json:"mime,omitempty"`
	Open      KindCap `json:"open"`
	Thumbnail KindCap `json:"thumbnail"`
}

Kind is one row of Admin → Plugins → Default apps.

type KindCap

type KindCap struct {
	On     []Handler `json:"on"`
	Off    []Handler `json:"off"`
	Custom bool      `json:"custom"`
	Rule   *Rule     `json:"rule,omitempty"`
}

KindCap is one capability of one kind, as the screen draws it.

type Place

type Place string

Place is where an install puts a new app's handler for one kind.

const (
	PlaceFirst Place = "first"
	PlaceLast  Place = "last"
	PlaceOff   Place = "off"
)

Places an install may choose.

type Placement

type Placement struct {
	Capability string `json:"capability"`
	Ext        string `json:"ext"`
	// Handler is the new app's handler for that capability.
	Handler string `json:"handler"`
	Place   Place  `json:"place"`
}

Placement is one choice an administrator made at install.

type Rule

type Rule struct {
	// Order are the handlers asked first, in this order.
	Order []string `json:"order"`
	// Off are the handlers switched off for this kind.
	Off []string `json:"off"`
}

Rule is the administrator's decision for one kind and one capability.

func Clean

func Clean(r Rule) Rule

Clean normalises a rule a caller wrote: ids trimmed, duplicates dropped, an id in both lists kept as off. It does not judge whether an id exists.

type Service

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

Service answers the chains and keeps the rules.

func New

func New(store Store) *Service

New builds the service over store. The source and the built-in drawer are attached once they exist (SetSource, SetBuiltinThumb).

func (*Service) Available

func (s *Service) Available(capability, name, mime string) []Handler

Available is every handler that could do the capability for a file of this name and type, in the default order - before any rule.

func (*Service) BuiltinThumb

func (s *Service) BuiltinThumb(name, mime string) bool

BuiltinThumb reports whether filex draws a file of this name and type.

func (*Service) Chain

func (s *Service) Chain(ctx context.Context, capability, name, mime string) Chain

Chain is the handlers of the capability for a file of this name and type: the available ones (Available), ordered and switched off by the rule for the file's kind.

⚠ The thumbnail pipeline asks this for every file it draws and every row a listing assesses, so it reads only memory: the source's list (a handful of apps) and the cached rules.

func (*Service) Check

func (s *Service) Check(capability, ext string, r Rule) error

Check refuses a rule Put would refuse, without storing anything: an unknown capability or kind, an id of the wrong shape, or a handler the kind does not have here.

func (*Service) Forget

func (s *Service) Forget()

Forget drops the rules read from the database; the next question reads them again.

func (*Service) InstallKinds

func (s *Service) InstallKinds(ctx context.Context, open, thumb []AppHandler) []InstallKind

InstallKinds lists the rows of the File types group for an app that is not installed yet: its open handlers (one per view) and its thumbnail handler, each kind they name - their extensions, and the known extensions of their media types.

func (*Service) Kinds

func (s *Service) Kinds(ctx context.Context) []Kind

Kinds lists every kind an app handles (its extensions, and the known extensions of its media types), every kind the document server opens as a choice while OnlyOffice is configured (`.csv`, filex 0.51) and every kind with a rule, sorted.

⚠ A kind only filex handles is not listed: there is nothing to choose between. Its rule, once written, keeps it on the list.

func (*Service) OnlyOfficeOpen added in v0.51.0

func (s *Service) OnlyOfficeOpen(name, mime string) bool

OnlyOfficeOpen reports whether the document server opens a file of this name and type now, as one choice among others.

func (*Service) OnlyOfficeThumb

func (s *Service) OnlyOfficeThumb(name, mime string) bool

OnlyOfficeThumb reports whether the document server draws a file of this name and type now.

func (*Service) OpenAllowed

func (s *Service) OpenAllowed(ctx context.Context, name, id string) bool

OpenAllowed reports whether the open handler id may open a file of this name: false only when the administrator switched it off for that kind. It does not judge whether the handler opens the kind at all - the view's own rule does that.

func (*Service) Place

func (s *Service) Place(ctx context.Context, p Placement, by *int64) error

Place writes the install-time choice for one kind: the new handler first, after the ones already there, or off. The order the kind has now (its rule, or the default) is written out whole, so the choice does not move anybody else.

func (*Service) PlaceForApp

func (s *Service) PlaceForApp(ctx context.Context, app string, placements []Placement, only map[string]bool, by *int64) []string

PlaceForApp writes the File types choices of an install, an upgrade or an approved request, and answers the ones it could not write (the app is installed either way; the screen says which kinds kept their order).

⚠ Two refusals, both about whose decision it is:

  • a choice that names ANOTHER app's handler: the install decides where THIS app goes, nothing else;
  • with only set (an upgrade), a choice for a kind not in it: the order the administrator already has for a kind the app handled before stays as it is.

func (*Service) PruneApp

func (s *Service) PruneApp(ctx context.Context, app string) error

PruneApp drops an app's handlers from every rule (the app was removed): the others keep their order, and a rule left with nothing in it goes.

func (*Service) Put

func (s *Service) Put(ctx context.Context, capability, ext string, r Rule, by *int64) (*Rule, error)

Put stores the administrator's rule for one kind and capability, after checking that it names only handlers the kind has: an id that is not one of them is refused rather than kept for later, so what the screen shows is what is stored.

func (*Service) Reset

func (s *Service) Reset(ctx context.Context, capability, ext string) (bool, error)

Reset removes the rule: the kind keeps the default order again. ok = there was one.

func (*Service) Rule

func (s *Service) Rule(ctx context.Context, capability, ext string) *Rule

Rule is the administrator's rule for a kind and a capability, nil for none.

func (*Service) Rules

func (s *Service) Rules(ctx context.Context, capability string) map[string]Rule

Rules is every rule of one capability, by kind.

func (*Service) SetBuiltinThumb

func (s *Service) SetBuiltinThumb(f func(name, mime string) bool)

SetBuiltinThumb attaches the answer to "does filex draw this file itself".

func (*Service) SetOnlyOfficeOpen added in v0.51.0

func (s *Service) SetOnlyOfficeOpen(f func(name, mime string) bool)

SetOnlyOfficeOpen attaches the answer to "does the document server open this file now, as one choice among others" (OnlyOffice configured, and a kind of OnlyOfficeOpens). Read on every open chain, so it must answer from memory.

func (*Service) SetOnlyOfficeThumb

func (s *Service) SetOnlyOfficeThumb(f func(name, mime string) bool)

SetOnlyOfficeThumb attaches the answer to "does the document server draw this file now" (OnlyOffice configured, and a kind it draws). Read on every chain, so it must answer from memory.

func (*Service) SetSource

func (s *Service) SetSource(src Source)

SetSource attaches (or replaces) the app handler source.

type Source

type Source interface {
	OpenHandlers() []AppHandler
	ThumbnailHandlers() []AppHandler
}

Source lists the app handlers that exist now: the running apps' interfaces that open files, and the running apps that draw thumbnails. The app registry implements it (internal/wasmplugin). Each list is in the order the default puts it in: by app name, then the app's own order.

type Store

type Store interface {
	ListFileAssociations(ctx context.Context) ([]*model.FileAssociation, error)
	PutFileAssociation(ctx context.Context, a *model.FileAssociation) error
	DeleteFileAssociation(ctx context.Context, capability, ext string) (bool, error)
}

Store is the slice of db.Store the service reads and writes.

Jump to

Keyboard shortcuts

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