starting on screen:webshare feature. simplify bookmarks (removed bookmarked from line)

This commit is contained in:
sawka 2023-03-24 10:34:07 -07:00
parent 8299d3ff54
commit bfe8ee1c02
12 changed files with 284 additions and 130 deletions

View File

@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS "bookmark_cmd" (
bookmarkid varchar(36) NOT NULL,
screenid varchar(36) NOT NULL,
cmdid varchar(36) NOT NULL,
PRIMARY KEY (bookmarkid, screenid, cmdid)
);
ALTER TABLE line ADD COLUMN bookmarked boolean NOT NULL DEFAULT 0;

View File

@ -0,0 +1,3 @@
DROP TABLE bookmark_cmd;
ALTER TABLE line DROP COLUMN bookmarked;

View File

@ -0,0 +1,4 @@
DROP TABLE screenupdates;
ALTER TABLE screen DROP COLUMN webshareopts;

View File

@ -0,0 +1,10 @@
CREATE TABLE screenupdates (
updateid integer PRIMARY KEY,
screenid varchar(36) NOT NULL,
lineid varchar(36) NOT NULL,
updatetype varchar(50) NOT NULL,
updatets bigint NOT NULL
);
ALTER TABLE screen ADD COLUMN webshareopts json NOT NULL DEFAULT 'null';

View File

@ -128,12 +128,6 @@ CREATE TABLE cloud_update (
updatetype varchar(50) NOT NULL,
updatekeys json NOT NULL
);
CREATE TABLE IF NOT EXISTS "bookmark_cmd" (
bookmarkid varchar(36) NOT NULL,
screenid varchar(36) NOT NULL,
cmdid varchar(36) NOT NULL,
PRIMARY KEY (bookmarkid, screenid, cmdid)
);
CREATE TABLE cmd_migrate (
sessionid varchar(36) NOT NULL,
screenid varchar(36) NOT NULL,
@ -155,7 +149,7 @@ CREATE TABLE IF NOT EXISTS "screen" (
anchor json NOT NULL,
focustype varchar(12) NOT NULL,
archived boolean NOT NULL,
archivedts bigint NOT NULL,
archivedts bigint NOT NULL, webshareopts json NOT NULL DEFAULT 'null',
PRIMARY KEY (screenid)
);
CREATE TABLE IF NOT EXISTS "line" (
@ -174,7 +168,6 @@ CREATE TABLE IF NOT EXISTS "line" (
star int NOT NULL,
archived boolean NOT NULL,
renderer varchar(50) NOT NULL,
bookmarked boolean NOT NULL,
PRIMARY KEY (screenid, lineid)
);
CREATE TABLE IF NOT EXISTS "cmd" (
@ -199,3 +192,10 @@ CREATE TABLE IF NOT EXISTS "cmd" (
rtndiffhasharr json NOT NULL,
PRIMARY KEY (screenid, cmdid)
);
CREATE TABLE screenupdates (
updateid integer PRIMARY KEY,
screenid varchar(36) NOT NULL,
lineid varchar(36) NOT NULL,
updatetype varchar(50) NOT NULL,
updatets bigint NOT NULL
);

View File

@ -3,6 +3,8 @@ package cmdrunner
import (
"bytes"
"context"
"crypto/rand"
"encoding/base64"
"fmt"
"log"
"os"
@ -12,6 +14,7 @@ import (
"strings"
"syscall"
"time"
"unicode"
"github.com/alessio/shellescape"
"github.com/google/uuid"
@ -40,6 +43,7 @@ func init() {
const DefaultUserId = "sawka"
const MaxNameLen = 50
const MaxShareNameLen = 150
const MaxRendererLen = 50
const MaxRemoteAliasLen = 50
const PasswordUnchangedSentinel = "--unchanged--"
@ -131,7 +135,6 @@ func init() {
registerCmdFn("session:showall", SessionShowAllCommand)
registerCmdFn("session:show", SessionShowCommand)
registerCmdFn("session:openshared", SessionOpenSharedCommand)
registerCmdFn("session:opencloud", SessionOpenCloudCommand)
registerCmdFn("screen", ScreenCommand)
registerCmdFn("screen:archive", ScreenArchiveCommand)
@ -141,6 +144,7 @@ func init() {
registerCmdFn("screen:set", ScreenSetCommand)
registerCmdFn("screen:showall", ScreenShowAllCommand)
registerCmdFn("screen:reset", ScreenResetCommand)
registerCmdFn("screen:webshare", ScreenWebShareCommand)
registerCmdAlias("remote", RemoteCommand)
registerCmdFn("remote:show", RemoteShowCommand)
@ -1561,6 +1565,18 @@ func validateName(name string, typeStr string) error {
return nil
}
func validateShareName(name string) error {
if len(name) > MaxShareNameLen {
return fmt.Errorf("share name too long, max length is %d", MaxShareNameLen)
}
for _, ch := range name {
if !unicode.IsPrint(ch) {
return fmt.Errorf("invalid character %q in share name", string(ch))
}
}
return nil
}
func validateRenderer(renderer string) error {
if renderer == "" {
return nil
@ -1601,22 +1617,6 @@ func SessionOpenSharedCommand(ctx context.Context, pk *scpacket.FeCommandPacketT
return nil, fmt.Errorf("shared sessions are not available in this version of prompt (stay tuned)")
}
func SessionOpenCloudCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
activate := resolveBool(pk.Kwargs["activate"], true)
newName := pk.Kwargs["name"]
if newName != "" {
err := validateName(newName, "session")
if err != nil {
return nil, err
}
}
update, err := sstore.InsertSessionWithName(ctx, newName, sstore.ShareModeShared, activate)
if err != nil {
return nil, err
}
return update, nil
}
func SessionOpenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
activate := resolveBool(pk.Kwargs["activate"], true)
newName := pk.Kwargs["name"]
@ -1633,6 +1633,53 @@ func SessionOpenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
return update, nil
}
func ScreenWebShareCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Screen)
if err != nil {
return nil, err
}
shouldShare := true
if len(pk.Args) > 0 {
shouldShare = resolveBool(pk.Args[0], true)
}
shareName := pk.Kwargs["sharename"]
if err := validateShareName(shareName); err != nil {
return nil, err
}
var infoMsg string
if shouldShare {
viewKeyBytes := make([]byte, 9)
_, err = rand.Read(viewKeyBytes)
if err != nil {
return nil, fmt.Errorf("cannot create viewkey: %v", err)
}
webShareOpts := sstore.ScreenWebShareOpts{ShareName: shareName, ViewKey: base64.RawURLEncoding.EncodeToString(viewKeyBytes)}
err = sstore.ScreenWebShareStart(ctx, ids.ScreenId, webShareOpts)
if err != nil {
return nil, fmt.Errorf("cannot web-share screen: %v", err)
}
pcloud.NotifyUpdateWriter()
infoMsg = fmt.Sprintf("screen is now shared to the web at %s", "[screen-share-url]")
} else {
err = sstore.ScreenWebShareStop(ctx, ids.ScreenId)
if err != nil {
return nil, fmt.Errorf("cannot stop web-sharing screen: %v", err)
}
infoMsg = fmt.Sprintf("screen is no longer web shared")
}
screen, err := sstore.GetScreenById(ctx, ids.ScreenId)
if err != nil {
return nil, fmt.Errorf("cannot get updated screen: %v", err)
}
update := sstore.ModelUpdate{
Screens: []*sstore.ScreenType{screen},
Info: &sstore.InfoMsgType{
InfoMsg: infoMsg,
},
}
return update, nil
}
func SessionDeleteCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
ids, err := resolveUiIds(ctx, pk, R_Session)
if err != nil {
@ -2339,36 +2386,42 @@ func LineBookmarkCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
if lineId == "" {
return nil, fmt.Errorf("line %q not found", lineArg)
}
lineObj, cmdObj, err := sstore.GetLineCmdByLineId(ctx, ids.ScreenId, lineId)
_, cmdObj, err := sstore.GetLineCmdByLineId(ctx, ids.ScreenId, lineId)
if err != nil {
return nil, fmt.Errorf("/line:bookmark error getting line: %v", err)
}
if cmdObj == nil {
return nil, fmt.Errorf("cannot bookmark non-cmd line")
}
ck := base.MakeCommandKey(lineObj.ScreenId, cmdObj.CmdId)
bm := &sstore.BookmarkType{
BookmarkId: uuid.New().String(),
CreatedTs: time.Now().UnixMilli(),
CmdStr: cmdObj.CmdStr,
Alias: "",
Tags: nil,
Description: "",
Cmds: []base.CommandKey{ck},
}
err = sstore.InsertBookmark(ctx, bm)
existingBmIds, err := sstore.GetBookmarkIdsByCmdStr(ctx, cmdObj.CmdStr)
if err != nil {
return nil, fmt.Errorf("cannot insert bookmark: %v", err)
return nil, fmt.Errorf("error trying to retrieve current boookmarks: %v", err)
}
newLineObj, err := sstore.GetLineById(ctx, ids.ScreenId, lineId)
if err != nil {
return nil, fmt.Errorf("/line:bookmark error getting line: %v", err)
var newBmId string
if len(existingBmIds) > 0 {
newBmId = existingBmIds[0]
} else {
newBm := &sstore.BookmarkType{
BookmarkId: uuid.New().String(),
CreatedTs: time.Now().UnixMilli(),
CmdStr: cmdObj.CmdStr,
Alias: "",
Tags: nil,
Description: "",
}
err = sstore.InsertBookmark(ctx, newBm)
if err != nil {
return nil, fmt.Errorf("cannot insert bookmark: %v", err)
}
newBmId = newBm.BookmarkId
}
if newLineObj == nil {
// no line (which is strange given we checked for it above). just return a nop.
return nil, nil
bms, err := sstore.GetBookmarks(ctx, "")
update := sstore.ModelUpdate{
MainView: sstore.MainViewBookmarks,
Bookmarks: bms,
SelectedBookmark: newBmId,
}
return sstore.ModelUpdate{Line: newLineObj}, nil
return update, nil
}
func LinePinCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {

View File

@ -209,3 +209,6 @@ func CreateCloudSession(ctx context.Context) error {
}
return nil
}
func NotifyUpdateWriter() {
}

View File

@ -663,7 +663,8 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
Archived: false,
ArchivedTs: 0,
}
query = `INSERT INTO screen (sessionid, screenid, name, screenidx, screenopts, ownerid, sharemode, curremoteownerid, curremoteid, curremotename, nextlinenum, selectedline, anchor, focustype, archived, archivedts) VALUES (:sessionid,:screenid,:name,:screenidx,:screenopts,:ownerid,:sharemode,:curremoteownerid,:curremoteid,:curremotename,:nextlinenum,:selectedline,:anchor,:focustype,:archived,:archivedts)`
query = `INSERT INTO screen ( sessionid, screenid, name, screenidx, screenopts, ownerid, sharemode, webshareopts, curremoteownerid, curremoteid, curremotename, nextlinenum, selectedline, anchor, focustype, archived, archivedts)
VALUES (:sessionid,:screenid,:name,:screenidx,:screenopts,:ownerid,:sharemode,:webshareopts,:curremoteownerid,:curremoteid,:curremotename,:nextlinenum,:selectedline,:anchor,:focustype,:archived,:archivedts)`
tx.NamedExec(query, screen.ToMap())
if activate {
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
@ -775,8 +776,8 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
query = `SELECT nextlinenum FROM screen WHERE screenid = ?`
nextLineNum := tx.GetInt(query, line.ScreenId)
line.LineNum = int64(nextLineNum)
query = `INSERT INTO line ( screenid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, renderer, ephemeral, contentheight, star, archived, bookmarked)
VALUES (:screenid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:renderer,:ephemeral,:contentheight,:star,:archived,:bookmarked)`
query = `INSERT INTO line ( screenid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, cmdid, renderer, ephemeral, contentheight, star, archived)
VALUES (:screenid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:cmdid,:renderer,:ephemeral,:contentheight,:star,:archived)`
tx.NamedExec(query, line)
query = `UPDATE screen SET nextlinenum = ? WHERE screenid = ?`
tx.Exec(query, nextLineNum+1, line.ScreenId)
@ -943,8 +944,6 @@ func cleanScreenCmds(ctx context.Context, screenId string) error {
removedCmds = tx.SelectStrings(query, screenId, screenId)
query = `DELETE FROM cmd WHERE screenid = ? AND cmdid NOT IN (SELECT cmdid FROM line WHERE screenid = ?)`
tx.Exec(query, screenId, screenId)
query = `DELETE FROM bookmark_cmd WHERE screenid = ? AND cmdid NOT IN (SELECT cmdid FROM cmd WHERE screenid = ?)`
tx.Exec(query, screenId, screenId)
return nil
})
if txErr != nil {
@ -2039,12 +2038,6 @@ type bookmarkOrderType struct {
OrderIdx int64
}
type bookmarkCmdType struct {
BookmarkId string
ScreenId string
CmdId string
}
func GetBookmarks(ctx context.Context, tag string) ([]*BookmarkType, error) {
var bms []*BookmarkType
txErr := WithTx(ctx, func(tx *TxWrap) error {
@ -2066,15 +2059,6 @@ func GetBookmarks(ctx context.Context, tag string) ([]*BookmarkType, error) {
bm.OrderIdx = bmOrder.OrderIdx
}
}
var cmds []bookmarkCmdType
query = `SELECT bookmarkid, screenid, cmdid FROM bookmark_cmd`
tx.Select(&cmds, query)
for _, cmd := range cmds {
bm := bmMap[cmd.BookmarkId]
if bm != nil {
bm.Cmds = append(bm.Cmds, base.MakeCommandKey(cmd.ScreenId, cmd.CmdId))
}
}
return nil
})
if txErr != nil {
@ -2094,12 +2078,6 @@ func GetBookmarkById(ctx context.Context, bookmarkId string, tag string) (*Bookm
query = `SELECT orderidx FROM bookmark_order WHERE bookmarkid = ? AND tag = ?`
orderIdx := tx.GetInt(query, bookmarkId, tag)
rtn.OrderIdx = int64(orderIdx)
query = `SELECT bookmarkid, screenid, cmdid FROM bookmark_cmd WHERE bookmarkid = ?`
var cmds []bookmarkCmdType
tx.Select(&cmds, query, bookmarkId)
for _, cmd := range cmds {
rtn.Cmds = append(rtn.Cmds, base.MakeCommandKey(cmd.ScreenId, cmd.CmdId))
}
return nil
})
if txErr != nil {
@ -2126,6 +2104,14 @@ func GetBookmarkIdByArg(ctx context.Context, bookmarkArg string) (string, error)
return rtnId, nil
}
func GetBookmarkIdsByCmdStr(ctx context.Context, cmdStr string) ([]string, error) {
return WithTxRtn(ctx, func(tx *TxWrap) ([]string, error) {
query := `SELECT bookmarkid FROM bookmark WHERE cmdstr = ?`
bmIds := tx.SelectStrings(query, cmdStr)
return bmIds, nil
})
}
// ignores OrderIdx field
func InsertBookmark(ctx context.Context, bm *BookmarkType) error {
if bm == nil || bm.BookmarkId == "" {
@ -2145,14 +2131,6 @@ func InsertBookmark(ctx context.Context, bm *BookmarkType) error {
query = `INSERT INTO bookmark_order (tag, bookmarkid, orderidx) VALUES (?, ?, ?)`
tx.Exec(query, tag, bm.BookmarkId, maxOrder+1)
}
query = `INSERT INTO bookmark_cmd (bookmarkid, screenid, cmdid) VALUES (?, ?, ?)`
for _, ck := range bm.Cmds {
tx.Exec(query, bm.BookmarkId, ck.GetGroupId(), ck.GetCmdId())
}
query = `UPDATE line SET bookmarked = 1 WHERE screenid = ? AND cmdid = ?`
for _, ck := range bm.Cmds {
tx.Exec(query, ck.GetGroupId(), ck.GetCmdId())
}
return nil
})
return txErr
@ -2205,10 +2183,6 @@ func DeleteBookmark(ctx context.Context, bookmarkId string) error {
tx.Exec(query, bookmarkId)
query = `DELETE FROM bookmark_order WHERE bookmarkid = ?`
tx.Exec(query, bookmarkId)
query = `UPDATE line SET bookmarked = 0 WHERE bookmarked AND cmdid <> '' AND (screenid||cmdid) IN (SELECT screenid||cmdid FROM bookmark_cmd WHERE bookmarkid = ?) `
tx.Exec(query, bookmarkId)
query = `DELETE FROM bookmark_cmd WHERE bookmarkid = ?`
tx.Exec(query, bookmarkId)
fixupBookmarkOrder(tx)
return nil
})
@ -2343,3 +2317,47 @@ func PurgeHistoryByIds(ctx context.Context, historyIds []string) ([]*HistoryItem
return rtn, nil
})
}
func ScreenWebShareStart(ctx context.Context, screenId string, shareOpts ScreenWebShareOpts) error {
return WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT screenid FROM screen WHERE screenid = ?`
if !tx.Exists(query, screenId) {
return fmt.Errorf("screen does not exist")
}
shareMode := tx.GetString(`SELECT sharemode FROM screen WHERE screenid = ?`, screenId)
if shareMode == ShareModeWeb {
return fmt.Errorf("screen is already shared to web")
}
if shareMode != ShareModeLocal {
return fmt.Errorf("screen cannot be shared, invalid current share mode %q (must be local)", shareMode)
}
query = `UPDATE screen SET sharemode = ?, webshareopts = ? WHERE screenid = ?`
tx.Exec(query, ShareModeWeb, quickJson(shareOpts), screenId)
query = `INSERT INTO screenupdates (screenid, lineid, updatetype, updatets)
SELECT screenid, lineid, ?, ? FROM line WHERE screenid = ? ORDER BY linenum`
tx.Exec(query, UpdateType_LineNew, time.Now().UnixMilli(), screenId)
return nil
})
}
func ScreenWebShareStop(ctx context.Context, screenId string) error {
return WithTx(ctx, func(tx *TxWrap) error {
query := `SELECT screenid FROM screen WHERE screenid = ?`
if !tx.Exists(query, screenId) {
return fmt.Errorf("screen does not exist")
}
shareMode := tx.GetString(`SELECT sharemode FROM screen WHERE screenid = ?`, screenId)
if shareMode != ShareModeWeb {
return fmt.Errorf("screen is not currently shared to the web")
}
query = `UPDATE screen SET sharemode = ?, webshareopts = ? WHERE screenid = ?`
tx.Exec(query, ShareModeLocal, "null", screenId)
query = `DELETE FROM screenupdates WHERE screenid = ?`
tx.Exec(query, screenId)
return nil
})
}
func isWebShare(tx *TxWrap, screenId string) bool {
return tx.Exists(`SELECT screenid FROM screen WHERE screenid = ? AND sharemode = ?`, screenId, ShareModeWeb)
}

View File

@ -17,7 +17,7 @@ import (
"github.com/golang-migrate/migrate/v4"
)
const MaxMigration = 13
const MaxMigration = 15
const MigratePrimaryScreenVersion = 9
func MakeMigrate() (*migrate.Migrate, error) {

View File

@ -80,6 +80,21 @@ func quickSetJson(ptr interface{}, m map[string]interface{}, name string) {
json.Unmarshal([]byte(str), ptr)
}
func quickSetNullableJson(ptr interface{}, m map[string]interface{}, name string) {
v, ok := m[name]
if !ok {
return
}
str, ok := v.(string)
if !ok {
return
}
if str == "" {
str = "null"
}
json.Unmarshal([]byte(str), ptr)
}
func quickSetJsonArr(ptr interface{}, m map[string]interface{}, name string) {
v, ok := m[name]
if !ok {
@ -95,6 +110,14 @@ func quickSetJsonArr(ptr interface{}, m map[string]interface{}, name string) {
json.Unmarshal([]byte(str), ptr)
}
func quickNullableJson(v interface{}) string {
if v == nil {
return "null"
}
barr, _ := json.Marshal(v)
return string(barr)
}
func quickJson(v interface{}) string {
if v == nil {
return "{}"

View File

@ -54,10 +54,8 @@ const (
)
const (
ShareModeLocal = "local"
ShareModePrivate = "private"
ShareModeView = "view"
ShareModeShared = "shared"
ShareModeLocal = "local"
ShareModeWeb = "web"
)
const (
@ -81,6 +79,19 @@ const (
CmdStoreTypeScreen = "screen"
)
const (
UpdateType_ScreenName = "screen:sharename"
UpdateType_ScreenCurRemote = "screen:curremote"
UpdateType_LineNew = "line:new"
UpdateType_LineDel = "line:del"
UpdateType_LineArchived = "line:archived"
UpdateType_LineRenderer = "line:renderer"
UpdateType_CmdStatus = "cmd:status"
UpdateType_CmdDoneInfo = "cmd:doneinfo"
UpdateType_CmdRunOut = "cmd:runout"
UpdateType_CmdRtnState = "cmd:rtnstate"
)
const MaxTzNameLen = 50
var globalDBLock = &sync.Mutex{}
@ -212,6 +223,7 @@ type ClientData struct {
FeOpts FeOptsType `json:"feopts"`
CmdStoreType string `json:"cmdstoretype"`
Migration *ClientMigrationData `json:"migration,omitempty" dbmap:"-"`
DBVersion int `json:"dbversion" dbmap:"-"`
}
func (ClientData) UseDBMap() {}
@ -401,21 +413,27 @@ type ScreenLinesType struct {
func (ScreenLinesType) UseDBMap() {}
type ScreenWebShareOpts struct {
ShareName string `json:"sharename"`
ViewKey string `json:"viewkey"`
}
type ScreenType struct {
SessionId string `json:"sessionid"`
ScreenId string `json:"screenid"`
Name string `json:"name"`
ScreenIdx int64 `json:"screenidx"`
ScreenOpts ScreenOptsType `json:"screenopts"`
OwnerId string `json:"ownerid"`
ShareMode string `json:"sharemode"`
CurRemote RemotePtrType `json:"curremote"`
NextLineNum int64 `json:"nextlinenum"`
SelectedLine int64 `json:"selectedline"`
Anchor ScreenAnchorType `json:"anchor"`
FocusType string `json:"focustype"`
Archived bool `json:"archived,omitempty"`
ArchivedTs int64 `json:"archivedts,omitempty"`
SessionId string `json:"sessionid"`
ScreenId string `json:"screenid"`
Name string `json:"name"`
ScreenIdx int64 `json:"screenidx"`
ScreenOpts ScreenOptsType `json:"screenopts"`
OwnerId string `json:"ownerid"`
ShareMode string `json:"sharemode"`
WebShareOpts *ScreenWebShareOpts `json:"webshareopts,omitempty"`
CurRemote RemotePtrType `json:"curremote"`
NextLineNum int64 `json:"nextlinenum"`
SelectedLine int64 `json:"selectedline"`
Anchor ScreenAnchorType `json:"anchor"`
FocusType string `json:"focustype"`
Archived bool `json:"archived,omitempty"`
ArchivedTs int64 `json:"archivedts,omitempty"`
// only for updates
Full bool `json:"full,omitempty"`
@ -431,6 +449,7 @@ func (s *ScreenType) ToMap() map[string]interface{} {
rtn["screenopts"] = quickJson(s.ScreenOpts)
rtn["ownerid"] = s.OwnerId
rtn["sharemode"] = s.ShareMode
rtn["webshareopts"] = quickNullableJson(s.WebShareOpts)
rtn["curremoteownerid"] = s.CurRemote.OwnerId
rtn["curremoteid"] = s.CurRemote.RemoteId
rtn["curremotename"] = s.CurRemote.Name
@ -451,6 +470,7 @@ func (s *ScreenType) FromMap(m map[string]interface{}) bool {
quickSetJson(&s.ScreenOpts, m, "screenopts")
quickSetStr(&s.OwnerId, m, "ownerid")
quickSetStr(&s.ShareMode, m, "sharemode")
quickSetNullableJson(&s.WebShareOpts, m, "webshareopts")
quickSetStr(&s.CurRemote.OwnerId, m, "curremoteownerid")
quickSetStr(&s.CurRemote.RemoteId, m, "curremoteid")
quickSetStr(&s.CurRemote.Name, m, "curremotename")
@ -654,6 +674,16 @@ func (ri *RemoteInstance) ToMap() map[string]interface{} {
return rtn
}
type ScreenUpdateType struct {
UpdateId int64 `json:"updateid"`
ScreenId string `json:"screenid"`
LineId string `json:"lineid"`
UpdateType string `json:"updatetype"`
UpdateTs int64 `json:"updatets"`
}
func (ScreenUpdateType) UseDBMap() {}
type LineType struct {
ScreenId string `json:"screenid"`
UserId string `json:"userid"`
@ -669,7 +699,6 @@ type LineType struct {
Ephemeral bool `json:"ephemeral,omitempty"`
ContentHeight int64 `json:"contentheight,omitempty"`
Star bool `json:"star,omitempty"`
Bookmarked bool `json:"bookmarked,omitempty"`
Archived bool `json:"archived,omitempty"`
Remove bool `json:"remove,omitempty"`
}
@ -747,15 +776,14 @@ type PlaybookEntry struct {
}
type BookmarkType struct {
BookmarkId string `json:"bookmarkid"`
CreatedTs int64 `json:"createdts"`
CmdStr string `json:"cmdstr"`
Alias string `json:"alias,omitempty"`
Tags []string `json:"tags"`
Description string `json:"description"`
Cmds []base.CommandKey `json:"cmds"`
OrderIdx int64 `json:"orderidx"`
Remove bool `json:"remove,omitempty"`
BookmarkId string `json:"bookmarkid"`
CreatedTs int64 `json:"createdts"`
CmdStr string `json:"cmdstr"`
Alias string `json:"alias,omitempty"`
Tags []string `json:"tags"`
Description string `json:"description"`
OrderIdx int64 `json:"orderidx"`
Remove bool `json:"remove,omitempty"`
}
func (bm *BookmarkType) GetSimpleKey() string {
@ -1127,6 +1155,8 @@ func EnsureClientData(ctx context.Context) (*ClientData, error) {
if cdata == nil {
return nil, fmt.Errorf("no client data found")
}
dbVersion := tx.GetInt(`SELECT version FROM schema_migrations`)
cdata.DBVersion = dbVersion
return cdata, nil
})
if err != nil {

View File

@ -30,24 +30,25 @@ func (PtyDataUpdate) UpdateType() string {
}
type ModelUpdate struct {
Sessions []*SessionType `json:"sessions,omitempty"`
ActiveSessionId string `json:"activesessionid,omitempty"`
Screens []*ScreenType `json:"screens,omitempty"`
ScreenLines *ScreenLinesType `json:"screenlines,omitempty"`
Line *LineType `json:"line,omitempty"`
Lines []*LineType `json:"lines,omitempty"`
Cmd *CmdType `json:"cmd,omitempty"`
CmdLine *CmdLineType `json:"cmdline,omitempty"`
Info *InfoMsgType `json:"info,omitempty"`
ClearInfo bool `json:"clearinfo,omitempty"`
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
History *HistoryInfoType `json:"history,omitempty"`
Interactive bool `json:"interactive"`
Connect bool `json:"connect,omitempty"`
MainView string `json:"mainview,omitempty"`
Bookmarks []*BookmarkType `json:"bookmarks,omitempty"`
HistoryViewData *HistoryViewData `json:"historyviewdata,omitempty"`
ClientData *ClientData `json:"clientdata,omitempty"`
Sessions []*SessionType `json:"sessions,omitempty"`
ActiveSessionId string `json:"activesessionid,omitempty"`
Screens []*ScreenType `json:"screens,omitempty"`
ScreenLines *ScreenLinesType `json:"screenlines,omitempty"`
Line *LineType `json:"line,omitempty"`
Lines []*LineType `json:"lines,omitempty"`
Cmd *CmdType `json:"cmd,omitempty"`
CmdLine *CmdLineType `json:"cmdline,omitempty"`
Info *InfoMsgType `json:"info,omitempty"`
ClearInfo bool `json:"clearinfo,omitempty"`
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
History *HistoryInfoType `json:"history,omitempty"`
Interactive bool `json:"interactive"`
Connect bool `json:"connect,omitempty"`
MainView string `json:"mainview,omitempty"`
Bookmarks []*BookmarkType `json:"bookmarks,omitempty"`
SelectedBookmark string `json:"selectedbookmark,omitempty"`
HistoryViewData *HistoryViewData `json:"historyviewdata,omitempty"`
ClientData *ClientData `json:"clientdata,omitempty"`
}
func (ModelUpdate) UpdateType() string {