roost

package module
v0.0.0-...-bcb4cd5 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2023 License: LGPL-3.0 Imports: 19 Imported by: 0

README

Roost

This is a library for providing core functionallity neccesary for the Roost app. Roost is a life organizing app which is offline-first and is private by design.

Concepts

Roost is powered by Slick which in turn uses SQLCipher.

Identity

An identity in Roost comprises the constellation of devices you have Roost installed on and use.

Device

Either a phone, iPad or computer capable of running Roost.

Group

A set of identites you share a common database with. Colloquolly referred to as a "roost".

Topic

An organizing principle within a group to separate things.

Message

A message sent in a group that belongs to a specific topic.

Todo

A todo item in a group that belongs to a specific topic.

Application lifecycle

The Roost application is in the new state when it is initially created. As the sqlite database used is password protected, to initialize roost you need to provide a password. This is done by calling Initialize(password) with the desired password. This causes Roost to transition to the running state. After this has been done, subsequent creation of the Roost application will start in the locked state. This is then transitioned to the running state by calling Unlock(password). Users of the library can rely on platform-specific features to store this password or otherwise prompt the user to supply their own password.

To cleanly shutdown Roost call Shutdown. After this is called, the Roost instance should no longer be used.

new ----> running
            ^
locked -----/

Joining a device group

An initialized Roost application can join the device group for another identity by providing it's URLs to the existing identity, which in turns invites the device. Once that invite is approved, the device belongs to the device group and all data will be synced between both devices.

The diagram below illustrates newly created roost1 joining an identity which roost2 belongs to.

roost1                            roost2

GetDeviceLink()
           --- send via QR code ---->
                                  LinkDevice(link)
Leaving a device group

To leave a device group, call LeaveDeviceGroup(). This will destory all data on this device and return this Roost to a new state.

Device identification

Devices are identified by a name and type. These are arbitrary strings and its up to various implementing platforms to display these in a way that is useful to the user. Device names and types are not shared outside of your device group.

Updates

Notifications about updates to application state, updates to the data and errors encountered are provided by a channel which is returned by Updates().

Push notifications

Devices can register for push notifications by calling AddPushToken(token) and removing that token by calling DeletePushToken(token).

Groups

Groups are a set of identities you share a database with. Within a group you have any number of topics, which in turn contain any number of todos and messages.

Joining a group

To join a group with a person with whom you have joined no prior groups, you use the following steps.

joinee                            joiner
(has group)                       (wants to join group)

Invite(password)
               --> send QR code
                   via email ---> AcceptInvite(invite, password)

Documentation

Index

Constants

View Source
const (
	StateNew = iota
	StateLocked
	StateRunning

	UpdateAppState = iota
	UpdateGroupUpdate
	UpdateViewUpdate
	UpdateEntityUpdate
	UpdateIntroUpdate
	UpdateTransportStateUpdate
	UpdateMessagesFetched
	UpdateUnknown
	UpdateFinished

	MessagesPageSize = 20
)
View Source
const PageSize = 100

Variables

This section is empty.

Functions

This section is empty.

Types

type AppState

type AppState struct {
	State int
}

type Device

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

func (*Device) Name

func (d *Device) Name() string

func (*Device) Type

func (d *Device) Type() string

type Devices

type Devices struct {
	Count int
	// contains filtered or unexported fields
}

func (*Devices) Device

func (d *Devices) Device(i int) *Device

type EntityUpdate

type EntityUpdate struct {
	GroupID  []byte
	EntityID []byte
	// contains filtered or unexported fields
}

type GroupUpdate

type GroupUpdate struct {
	ID                   []byte
	AckedMemberCount     int
	GroupState           int
	MemberCount          int
	ConnectedMemberCount int
	Seq                  int64
	PendingMessageCount  int
}

type Groups

type Groups struct {
	Count int
	// contains filtered or unexported fields
}

func (*Groups) Group

func (g *Groups) Group(i int) *RoostGroup

type IntroUpdate

type IntroUpdate struct {
	GroupID   []byte
	Initiator bool
	Stage     int
	Type      int
}

type Message

type Message struct {
	ID           []byte  `db:"id"`
	GroupID      []byte  `db:"group_id"`
	CtimeSec     float64 `db:"_ctime"`
	MtimeSec     float64 `db:"_mtime"`
	WtimeSec     float64 `db:"_wtime"`
	IdentityID   []byte  `db:"_identity_tag"`
	MembershipID []byte  `db:"_membership_tag"`
	TopicID      []byte  `db:"topic_id"`
	Body         string  `db:"body"`
}

Message is a chat message sent within the context of a topic.

type PagedMessages

type PagedMessages struct {
	AtEnd  bool
	Cursor string
	Count  int
	// contains filtered or unexported fields
}

A container for paged messages which indicates if there are further messages and provides a cursor for continued paging.

func (*PagedMessages) Message

func (pm *PagedMessages) Message(i int) *Message

type Reaction

type Reaction struct {
	ID           []byte  `db:"id"`
	GroupID      []byte  `db:"group_id"`
	CtimeSec     float64 `db:"_ctime"`
	MtimeSec     float64 `db:"_mtime"`
	WtimeSec     float64 `db:"_wtime"`
	IdentityID   []byte  `db:"_identity_tag"`
	MembershipID []byte  `db:"_membership_tag"`
	Rune         string  `db:"rune"`
	Active       bool    `db:"active"`
	EntityID     []byte  `db:"entity_id"`
}

Reaction is a "rune" that refers to another entity (such as a message or todo item)

type Reactions

type Reactions struct {
	Count int
	// contains filtered or unexported fields
}

func (*Reactions) Reaction

func (r *Reactions) Reaction(i int) *Reaction

type Result

type Result struct {
	RowID     int64  `db:"rowid"`
	Text      string `db:"text"`
	EntityID  []byte `db:"entity_id"`
	GroupID   []byte `db:"group_id"`
	TopicID   []byte `db:"topic_id"`
	TopicName string `db:"topic_name"`
	Type      string `db:"type"`
}

type Roost

type Roost struct {
	State int
	// contains filtered or unexported fields
}

func MakeRoost

func MakeRoost(root, heyaAuthToken string) (*Roost, error)

Makes a Roost instance for a given root directory.

func MakeRoostWithKeyMaker

func MakeRoostWithKeyMaker(root, heyaAuthToken string, keyMaker keyMaker) (*Roost, error)

Makes a Roost instance with a given key maker. Not typically used outside of tests.

func MakeRoostWithStrongKey

func MakeRoostWithStrongKey(root, heyaAuthToken string) (*Roost, error)

Makes a Roost instance for a given root directory.

func (*Roost) AcceptInvite

func (r *Roost) AcceptInvite(inviteURL string, password string) ([]byte, error)

Accepts an invite.

func (*Roost) AddPushToken

func (r *Roost) AddPushToken(token string) error

Adds a push notification token to Roost.

func (*Roost) CreateGroup

func (r *Roost) CreateGroup(name string) (*RoostGroup, error)

Creates a roost group (a "roost")

func (*Roost) DeletePushToken

func (r *Roost) DeletePushToken(token string) error

Removes a push notification token from Roost.

func (*Roost) Devices

func (r *Roost) Devices() (*Devices, error)

Gets a list of all connected devices to the current identity.

func (r *Roost) GetDeviceLink() (string, error)

Gets a device link which can be used to link a device to the current device group.

func (*Roost) GetMessages

func (r *Roost) GetMessages(password string) error

Gets messages. Clients should wait for an UpdateMessagesFetched event and shutdown after that.

func (*Roost) Group

func (r *Roost) Group(groupID []byte) (*RoostGroup, error)

Gets a group for a specific id.

func (*Roost) Groups

func (r *Roost) Groups() (*Groups, error)

Gets a list of available groups.

func (*Roost) Initialize

func (r *Roost) Initialize(password string) error

Initializes roost with a given password.

func (*Roost) LeaveDeviceGroup

func (r *Roost) LeaveDeviceGroup() error

Leave a device group and destroy all Roost data on this device, returning it to a "new" state.

func (*Roost) LinkDevice

func (r *Roost) LinkDevice(l string) error

Links a device using the provided device link.

func (*Roost) NewPin

func (r *Roost) NewPin() (string, error)

Generates a random 6-digit pin

func (*Roost) NextPage

func (r *Roost) NextPage(results *SearchResults) (*SearchResults, error)

Fetch the next page of results from a previous search.

func (*Roost) RegisterHeyaTransport

func (r *Roost) RegisterHeyaTransport(authToken, host string, port int) error

Registers the HEYA transport which is the main transport used currently for Roost. This transport supports the sending of iOS push notifications.

func (*Roost) Search

func (r *Roost) Search(groupID []byte, term, highlightStart, highlightEnd string) (*SearchResults, error)

Perform a fulltext search across all your Roosts.

func (*Roost) SetDeviceNameType

func (r *Roost) SetDeviceNameType(name, ty string) error

Sets the current device name and type for a given roost instance.

func (*Roost) Shutdown

func (r *Roost) Shutdown() error

Shuts down an existing roost instance.

func (*Roost) Slick

func (r *Roost) Slick() *slick.Slick

Get the underlying Slick instance

func (*Roost) TransportStates

func (r *Roost) TransportStates() *TransportStates

Get current transport states

func (*Roost) Unlock

func (r *Roost) Unlock(password string) error

Unlocks an already initialized roost with a given password.

func (*Roost) UnreadMessageCount

func (r *Roost) UnreadMessageCount() (int64, error)

Return the number of unread messages across all topics and groups

func (*Roost) Updates

func (r *Roost) Updates() *Updates

Gets a channel of events which can occur within the application. For example application state changes and updates to specific tables within the EAV database.

This channel will provide the following types:

	*AppState: an update about the current state of Roost
  *GroupUpdate: an update about a group
  *TableUpdate: an update about a specific table within roost, for instance `todos`, `topics` or `messages`.

type RoostGroup

type RoostGroup struct {
	GroupID             []byte
	IdentityTag         []byte
	Name                string
	UnreadMessageCount  int
	IncompleteTodoCount int
	UnreadTodoCount     int
	// contains filtered or unexported fields
}

A group (or "roost") within Roost. This represents a set of identities collaborating together in the same database.

func (*RoostGroup) CancelInvites

func (rg *RoostGroup) CancelInvites() error

Cancels invites to this group.

func (*RoostGroup) CreateMessage

func (rg *RoostGroup) CreateMessage(topicID []byte, body string) (*Message, error)

Creates a message in a given topic id with a textual body.

func (*RoostGroup) CreateTodo

func (rg *RoostGroup) CreateTodo(topicID []byte, label string) (*Todo, error)

Creates a todo item in the given topic specified by id with a textual body.

func (*RoostGroup) CreateTopic

func (rg *RoostGroup) CreateTopic(label string) (*Topic, error)

CreateTopic creates a new topic with the given name.

func (*RoostGroup) CreateTopicPinned

func (rg *RoostGroup) CreateTopicPinned(label string, pinned bool) (*Topic, error)

func (*RoostGroup) DeleteTodo

func (rg *RoostGroup) DeleteTodo(id []byte) error

Gets a list of all connected devices to the current identity.

func (*RoostGroup) Invite

func (rg *RoostGroup) Invite(password string) (string, error)

Creates a password-protected invite.

func (*RoostGroup) MarkTopicRead

func (rg *RoostGroup) MarkTopicRead(topicID []byte) error

Mark a topic as read

func (*RoostGroup) Message

func (rg *RoostGroup) Message(id []byte) (*Message, error)

Gets a message for a given id.

func (*RoostGroup) Messages

func (rg *RoostGroup) Messages(topicID []byte, cursor string) (*PagedMessages, error)

Gets a list of messages for a given topic id and a cursor. If cursor is "", it retrieves messages in reverse chronological order. Otherwise, use the cursor value provided by PagedMessages.

func (*RoostGroup) MoveTodo

func (rg *RoostGroup) MoveTodo(complete bool, topicID []byte, from, to int) error

Moves a todo item in the given topic specified by id

func (*RoostGroup) MoveTopic

func (rg *RoostGroup) MoveTopic(pinned bool, from, to int) error

Moves a topic item in the given topic specified by id

func (*RoostGroup) PinTopic

func (rg *RoostGroup) PinTopic(topicID []byte, pinned bool) error

Pin a topic

func (*RoostGroup) Reactions

func (rg *RoostGroup) Reactions(entityID []byte) (*Reactions, error)

Get all reactions for a given entity id

func (*RoostGroup) SetReaction

func (rg *RoostGroup) SetReaction(entityID []byte, r string, active bool) error

Set a reaction to an entity

func (*RoostGroup) SetShowCompleted

func (rg *RoostGroup) SetShowCompleted(id []byte, completed bool) error

Set show completed

func (*RoostGroup) Todo

func (rg *RoostGroup) Todo(id []byte) (*Todo, error)

Gets a todo for a given id.

func (*RoostGroup) TodoUpdater

func (rg *RoostGroup) TodoUpdater() *TodoUpdater

Create a todo updater which can be used for marking todos complete en masse

func (*RoostGroup) Todos

func (rg *RoostGroup) Todos(topicID []byte) (*Todos, error)

Gets a list of todos for a given topic id.

func (*RoostGroup) Topic

func (rg *RoostGroup) Topic(id []byte) (*Topic, error)

Gets a topic for a given id.

func (*RoostGroup) Topics

func (rg *RoostGroup) Topics() (*Topics, error)

Gets a list of all topics.

func (*RoostGroup) UpdateMessage

func (rg *RoostGroup) UpdateMessage(message *Message) error

Updates a message.

func (*RoostGroup) UpdateTodo

func (rg *RoostGroup) UpdateTodo(todo *Todo) error

Updates a todo.

func (*RoostGroup) UpdateTopic

func (rg *RoostGroup) UpdateTopic(topic *Topic) error

Updates a topic in a group.

type SearchResults

type SearchResults struct {
	GroupID        []byte
	Term           string
	HighlightStart string
	HighlightEnd   string
	Offset         int
	Total          int
	Count          int
	// contains filtered or unexported fields
}

func (*SearchResults) Result

func (sr *SearchResults) Result(i int) *Result

type TableUpdate

type TableUpdate struct {
	ID        []byte
	Name      string
	Tablename string
}

type Todo

type Todo struct {
	ID                []byte  `db:"id"`
	GroupID           []byte  `db:"group_id"`
	CtimeSec          float64 `db:"_ctime"`
	MtimeSec          float64 `db:"_mtime"`
	WtimeSec          float64 `db:"_wtime"`
	IdentityID        []byte  `db:"_identity_tag"`
	MembershipID      []byte  `db:"_membership_tag"`
	TopicID           []byte  `db:"topic_id"`
	Body              string  `db:"body"`
	CompletedAt       float64 `db:"completed_at"`
	CompletedPosition float64 `db:"completed_position"`
	Deleted           bool    `db:"deleted"`
	Read              bool    `db:"read"`
	Position          float64 `db:"position"`
}

Todo item within a topic.

func (*Todo) Complete

func (t *Todo) Complete() bool

type TodoUpdater

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

func (*TodoUpdater) Commit

func (tu *TodoUpdater) Commit() error

also give them new positions when you complete them

func (*TodoUpdater) MarkComplete

func (tu *TodoUpdater) MarkComplete(id []byte, complete bool)

func (*TodoUpdater) MarkRead

func (tu *TodoUpdater) MarkRead(id []byte, read bool)

type Todos

type Todos struct {
	IncompleteCount int
	CompleteCount   int
	// contains filtered or unexported fields
}

func (*Todos) CompleteTodo

func (t *Todos) CompleteTodo(i int) *Todo

func (*Todos) IncompleteTodo

func (t *Todos) IncompleteTodo(i int) *Todo

type Topic

type Topic struct {
	ID                  []byte  `db:"id"`
	GroupID             []byte  `db:"group_id"`
	CtimeSec            float64 `db:"_ctime"`
	MtimeSec            float64 `db:"_mtime"`
	WtimeSec            float64 `db:"_wtime"`
	IdentityID          []byte  `db:"_identity_tag"`
	MembershipID        []byte  `db:"_membership_tag"`
	Label               string  `db:"label"`
	MessageLastRead     float64 `db:"message_last_read"`
	UnreadMessageCount  int     `db:"unread_message_count"`
	IncompleteTodoCount int     `db:"incomplete_todo_count"`
	UnreadTodoCount     int     `db:"unread_todo_count"`
	ShowCompleted       bool    `db:"show_completed"`
	Pinned              bool    `db:"pinned"`
	Position            float64 `db:"position"`
	PinPosition         float64 `db:"pin_position"`
}

Topic is a organizational structure within a group.

type Topics

type Topics struct {
	Count int
	// contains filtered or unexported fields
}

func (*Topics) Topic

func (t *Topics) Topic(i int) *Topic

type TransportStateUpdate

type TransportStateUpdate struct {
	URL   string
	State string
}

type TransportStates

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

func (*TransportStates) Len

func (t *TransportStates) Len() int

func (*TransportStates) State

func (t *TransportStates) State(i int) string

func (*TransportStates) URL

func (t *TransportStates) URL(i int) string

type Updates

type Updates struct {
	// contains filtered or unexported fields
}
	*AppState: an update about the current state of Roost
  *GroupUpdate: an update about a group
  *ViewUpdate: an update about a specific view within roost, for instance `todos`, `topics` or `messages`.
  *EntityUpdate: an update about a specific view row within roost, for instance `todos`, `topics` or `messages`.
  *IntroUpdate: an update about a specific table within roost, for instance `todos`, `topics` or `messages`.
  *StateUpdate: an update about a specific table within roost, for instance `todos`, `topics` or `messages`.

func (*Updates) AppState

func (u *Updates) AppState() *AppState

func (*Updates) GroupUpdate

func (u *Updates) GroupUpdate() *GroupUpdate

func (*Updates) IntroUpdate

func (u *Updates) IntroUpdate() *IntroUpdate

func (*Updates) Next

func (u *Updates) Next()

func (*Updates) TransportStateUpdate

func (u *Updates) TransportStateUpdate() *TransportStateUpdate

func (*Updates) Type

func (u *Updates) Type() int

func (*Updates) ViewEntityUpdate

func (u *Updates) ViewEntityUpdate() *EntityUpdate

func (*Updates) ViewUpdate

func (u *Updates) ViewUpdate() *ViewUpdate

type ViewUpdate

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

Jump to

Keyboard shortcuts

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