mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-10 19:58:00 +01:00
checkpoint, backend changes for consolidating window and screen_window to screen
This commit is contained in:
parent
ee2fd8e98f
commit
e154aacaad
@ -193,25 +193,20 @@ func HandleLogActiveState(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// params: sessionid, windowid
|
// params: screenid
|
||||||
func HandleGetWindow(w http.ResponseWriter, r *http.Request) {
|
func HandleGetFullScreen(w http.ResponseWriter, r *http.Request) {
|
||||||
qvals := r.URL.Query()
|
qvals := r.URL.Query()
|
||||||
sessionId := qvals.Get("sessionid")
|
screenId := qvals.Get("screenid")
|
||||||
windowId := qvals.Get("windowid")
|
if _, err := uuid.Parse(screenId); err != nil {
|
||||||
if _, err := uuid.Parse(sessionId); err != nil {
|
WriteJsonError(w, fmt.Errorf("invalid screenid: %w", err))
|
||||||
WriteJsonError(w, fmt.Errorf("invalid sessionid: %w", err))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := uuid.Parse(windowId); err != nil {
|
screen, err := sstore.GetFullScreenById(r.Context(), screenId)
|
||||||
WriteJsonError(w, fmt.Errorf("invalid windowid: %w", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
window, err := sstore.GetWindowById(r.Context(), sessionId, windowId)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
WriteJsonError(w, err)
|
WriteJsonError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
WriteJsonSuccess(w, window)
|
WriteJsonSuccess(w, screen)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,7 +562,7 @@ func main() {
|
|||||||
gr.HandleFunc("/api/ptyout", AuthKeyWrap(HandleGetPtyOut))
|
gr.HandleFunc("/api/ptyout", AuthKeyWrap(HandleGetPtyOut))
|
||||||
gr.HandleFunc("/api/remote-pty", AuthKeyWrap(HandleRemotePty))
|
gr.HandleFunc("/api/remote-pty", AuthKeyWrap(HandleRemotePty))
|
||||||
gr.HandleFunc("/api/rtnstate", AuthKeyWrap(HandleRtnState))
|
gr.HandleFunc("/api/rtnstate", AuthKeyWrap(HandleRtnState))
|
||||||
gr.HandleFunc("/api/get-window", AuthKeyWrap(HandleGetWindow))
|
gr.HandleFunc("/api/get-full-screen", AuthKeyWrap(HandleGetFullScreen))
|
||||||
gr.HandleFunc("/api/run-command", AuthKeyWrap(HandleRunCommand)).Methods("POST")
|
gr.HandleFunc("/api/run-command", AuthKeyWrap(HandleRunCommand)).Methods("POST")
|
||||||
gr.HandleFunc("/api/get-client-data", AuthKeyWrap(HandleGetClientData))
|
gr.HandleFunc("/api/get-client-data", AuthKeyWrap(HandleGetClientData))
|
||||||
gr.HandleFunc("/api/set-winsize", AuthKeyWrap(HandleSetWinSize))
|
gr.HandleFunc("/api/set-winsize", AuthKeyWrap(HandleSetWinSize))
|
||||||
|
3
db/migrations/000009_screenprimary.down.sql
Normal file
3
db/migrations/000009_screenprimary.down.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
-- invalid, will throw an error, cannot migrate down past 9
|
||||||
|
SELECT x;
|
||||||
|
|
56
db/migrations/000009_screenprimary.up.sql
Normal file
56
db/migrations/000009_screenprimary.up.sql
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
CREATE TABLE new_screen (
|
||||||
|
sessionid varchar(36) NOT NULL,
|
||||||
|
screenid varchar(36) NOT NULL,
|
||||||
|
windowid varchar(36) NOT NULL,
|
||||||
|
name varchar(50) NOT NULL,
|
||||||
|
screenidx int NOT NULL,
|
||||||
|
screenopts json NOT NULL,
|
||||||
|
ownerid varchar(36) NOT NULL,
|
||||||
|
sharemode varchar(12) NOT NULL,
|
||||||
|
curremoteownerid varchar(36) NOT NULL,
|
||||||
|
curremoteid varchar(36) NOT NULL,
|
||||||
|
curremotename varchar(50) NOT NULL,
|
||||||
|
nextlinenum int NOT NULL,
|
||||||
|
selectedline int NOT NULL,
|
||||||
|
anchor json NOT NULL,
|
||||||
|
focustype varchar(12) NOT NULL,
|
||||||
|
archived boolean NOT NULL,
|
||||||
|
archivedts bigint NOT NULL,
|
||||||
|
PRIMARY KEY (sessionid, screenid)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO new_screen
|
||||||
|
SELECT
|
||||||
|
s.sessionid,
|
||||||
|
s.screenid,
|
||||||
|
w.windowid,
|
||||||
|
s.name,
|
||||||
|
s.screenidx,
|
||||||
|
json_patch(s.screenopts, w.winopts),
|
||||||
|
s.ownerid,
|
||||||
|
s.sharemode,
|
||||||
|
w.curremoteownerid,
|
||||||
|
w.curremoteid,
|
||||||
|
w.curremotename,
|
||||||
|
w.nextlinenum,
|
||||||
|
sw.selectedline,
|
||||||
|
sw.anchor,
|
||||||
|
sw.focustype,
|
||||||
|
s.archived,
|
||||||
|
s.archivedts
|
||||||
|
FROM
|
||||||
|
screen s,
|
||||||
|
screen_window sw,
|
||||||
|
window w
|
||||||
|
WHERE
|
||||||
|
s.screenid = sw.screenid
|
||||||
|
AND sw.windowid = w.windowid
|
||||||
|
;
|
||||||
|
|
||||||
|
DROP TABLE screen;
|
||||||
|
DROP TABLE screen_window;
|
||||||
|
DROP TABLE window;
|
||||||
|
|
||||||
|
ALTER TABLE new_screen RENAME TO screen;
|
||||||
|
|
||||||
|
|
@ -151,7 +151,6 @@ func init() {
|
|||||||
registerCmdFn("remote:installcancel", RemoteInstallCancelCommand)
|
registerCmdFn("remote:installcancel", RemoteInstallCancelCommand)
|
||||||
registerCmdFn("remote:reset", RemoteResetCommand)
|
registerCmdFn("remote:reset", RemoteResetCommand)
|
||||||
|
|
||||||
registerCmdFn("sw:set", SwSetCommand)
|
|
||||||
registerCmdFn("sw:resize", SwResizeCommand)
|
registerCmdFn("sw:resize", SwResizeCommand)
|
||||||
|
|
||||||
// sw:resize
|
// sw:resize
|
||||||
@ -458,7 +457,7 @@ func ScreenArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/screen:archive cannot re-open screen: %v", err)
|
return nil, fmt.Errorf("/screen:archive cannot re-open screen: %v", err)
|
||||||
}
|
}
|
||||||
screen, err := sstore.GetScreenById(ctx, ids.SessionId, screenId)
|
screen, err := sstore.GetScreenById(ctx, screenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/screen:archive cannot get updated screen obj: %v", err)
|
return nil, fmt.Errorf("/screen:archive cannot get updated screen obj: %v", err)
|
||||||
}
|
}
|
||||||
@ -512,17 +511,17 @@ func ScreenSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var varsUpdated []string
|
var varsUpdated []string
|
||||||
|
var setNonAnchor bool // anchor does not receive an update
|
||||||
|
updateMap := make(map[string]interface{})
|
||||||
if pk.Kwargs["name"] != "" {
|
if pk.Kwargs["name"] != "" {
|
||||||
newName := pk.Kwargs["name"]
|
newName := pk.Kwargs["name"]
|
||||||
err = validateName(newName, "screen")
|
err = validateName(newName, "screen")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = sstore.SetScreenName(ctx, ids.SessionId, ids.ScreenId, newName)
|
updateMap[sstore.ScreenField_Name] = newName
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("setting screen name: %v", err)
|
|
||||||
}
|
|
||||||
varsUpdated = append(varsUpdated, "name")
|
varsUpdated = append(varsUpdated, "name")
|
||||||
|
setNonAnchor = true
|
||||||
}
|
}
|
||||||
if pk.Kwargs["tabcolor"] != "" {
|
if pk.Kwargs["tabcolor"] != "" {
|
||||||
color := pk.Kwargs["tabcolor"]
|
color := pk.Kwargs["tabcolor"]
|
||||||
@ -530,39 +529,67 @@ func ScreenSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
screenObj, err := sstore.GetScreenById(ctx, ids.SessionId, ids.ScreenId)
|
updateMap[sstore.ScreenField_TabColor] = color
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
opts := screenObj.ScreenOpts
|
|
||||||
if opts == nil {
|
|
||||||
opts = &sstore.ScreenOptsType{}
|
|
||||||
}
|
|
||||||
opts.TabColor = color
|
|
||||||
err = sstore.SetScreenOpts(ctx, ids.SessionId, ids.ScreenId, opts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("setting screen opts: %v", err)
|
|
||||||
}
|
|
||||||
varsUpdated = append(varsUpdated, "tabcolor")
|
varsUpdated = append(varsUpdated, "tabcolor")
|
||||||
|
setNonAnchor = true
|
||||||
}
|
}
|
||||||
if pk.Kwargs["pos"] != "" {
|
if pk.Kwargs["pos"] != "" {
|
||||||
|
|
||||||
varsUpdated = append(varsUpdated, "pos")
|
varsUpdated = append(varsUpdated, "pos")
|
||||||
|
setNonAnchor = true
|
||||||
|
}
|
||||||
|
if pk.Kwargs["focus"] != "" {
|
||||||
|
focusVal := pk.Kwargs["focus"]
|
||||||
|
if focusVal != sstore.ScreenFocusInput && focusVal != sstore.ScreenFocusCmd && focusVal != sstore.ScreenFocusCmdFg {
|
||||||
|
return nil, fmt.Errorf("/screen:set invalid focus argument %q, must be %s", focusVal, formatStrs([]string{sstore.ScreenFocusInput, sstore.ScreenFocusCmd, sstore.ScreenFocusCmdFg}, "or", false))
|
||||||
|
}
|
||||||
|
updateMap[sstore.ScreenField_Focus] = focusVal
|
||||||
|
setNonAnchor = true
|
||||||
|
}
|
||||||
|
if pk.Kwargs["line"] != "" {
|
||||||
|
screen, err := sstore.GetScreenById(ctx, ids.ScreenId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("/screen:set cannot get screen: %v", err)
|
||||||
|
}
|
||||||
|
var selectedLineStr string
|
||||||
|
if screen.SelectedLine > 0 {
|
||||||
|
selectedLineStr = strconv.Itoa(int(screen.SelectedLine))
|
||||||
|
}
|
||||||
|
ritem, err := resolveLine(ctx, screen.SessionId, screen.WindowId, pk.Kwargs["line"], selectedLineStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("/screen:set error resolving line: %v", err)
|
||||||
|
}
|
||||||
|
if ritem == nil {
|
||||||
|
return nil, fmt.Errorf("/screen:set could not resolve line %q", pk.Kwargs["line"])
|
||||||
|
}
|
||||||
|
setNonAnchor = true
|
||||||
|
updateMap[sstore.ScreenField_SelectedLine] = ritem.Num
|
||||||
|
}
|
||||||
|
if pk.Kwargs["anchor"] != "" {
|
||||||
|
m := swAnchorRe.FindStringSubmatch(pk.Kwargs["anchor"])
|
||||||
|
if m == nil {
|
||||||
|
return nil, fmt.Errorf("/screen:set invalid anchor argument (must be [line] or [line]:[offset])")
|
||||||
|
}
|
||||||
|
anchorLine, _ := strconv.Atoi(m[1])
|
||||||
|
updateMap[sstore.ScreenField_AnchorLine] = anchorLine
|
||||||
|
if m[2] != "" {
|
||||||
|
anchorOffset, _ := strconv.Atoi(m[2])
|
||||||
|
updateMap[sstore.ScreenField_AnchorOffset] = anchorOffset
|
||||||
|
} else {
|
||||||
|
updateMap[sstore.ScreenField_AnchorOffset] = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(varsUpdated) == 0 {
|
if len(varsUpdated) == 0 {
|
||||||
return nil, fmt.Errorf("/screen:set no updates, can set %s", formatStrs([]string{"name", "pos", "tabcolor"}, "or", false))
|
return nil, fmt.Errorf("/screen:set no updates, can set %s", formatStrs([]string{"name", "pos", "tabcolor", "focus", "anchor", "line"}, "or", false))
|
||||||
}
|
}
|
||||||
screenObj, err := sstore.GetScreenById(ctx, ids.SessionId, ids.ScreenId)
|
screen, err := sstore.UpdateScreen(ctx, ids.ScreenId, updateMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("error updating screen: %v", err)
|
||||||
}
|
}
|
||||||
bareSession, err := sstore.GetBareSessionById(ctx, ids.SessionId)
|
if !setNonAnchor {
|
||||||
if err != nil {
|
return nil, nil
|
||||||
return nil, fmt.Errorf("/screen:set cannot retrieve session: %v", err)
|
|
||||||
}
|
}
|
||||||
bareSession.Screens = append(bareSession.Screens, screenObj)
|
|
||||||
update := sstore.ModelUpdate{
|
update := sstore.ModelUpdate{
|
||||||
Sessions: []*sstore.SessionType{bareSession},
|
Screens: []*sstore.ScreenType{screen},
|
||||||
Info: &sstore.InfoMsgType{
|
Info: &sstore.InfoMsgType{
|
||||||
InfoMsg: fmt.Sprintf("screen updated %s", formatStrs(varsUpdated, "and", false)),
|
InfoMsg: fmt.Sprintf("screen updated %s", formatStrs(varsUpdated, "and", false)),
|
||||||
TimeoutMs: 2000,
|
TimeoutMs: 2000,
|
||||||
@ -593,69 +620,8 @@ func ScreenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstor
|
|||||||
|
|
||||||
var swAnchorRe = regexp.MustCompile("^(\\d+)(?::(-?\\d+))?$")
|
var swAnchorRe = regexp.MustCompile("^(\\d+)(?::(-?\\d+))?$")
|
||||||
|
|
||||||
func SwSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("/sw:set cannot resolve current screen-window: %w", err)
|
|
||||||
}
|
|
||||||
var setNonST bool // scrolltop does not receive an update
|
|
||||||
updateMap := make(map[string]interface{})
|
|
||||||
if pk.Kwargs["anchor"] != "" {
|
|
||||||
m := swAnchorRe.FindStringSubmatch(pk.Kwargs["anchor"])
|
|
||||||
if m == nil {
|
|
||||||
return nil, fmt.Errorf("/sw:set invalid anchor argument (must be [line] or [line]:[offset])")
|
|
||||||
}
|
|
||||||
anchorLine, _ := strconv.Atoi(m[1])
|
|
||||||
updateMap[sstore.SWField_AnchorLine] = anchorLine
|
|
||||||
if m[2] != "" {
|
|
||||||
anchorOffset, _ := strconv.Atoi(m[2])
|
|
||||||
updateMap[sstore.SWField_AnchorOffset] = anchorOffset
|
|
||||||
} else {
|
|
||||||
updateMap[sstore.SWField_AnchorOffset] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pk.Kwargs["focus"] != "" {
|
|
||||||
focusVal := pk.Kwargs["focus"]
|
|
||||||
if focusVal != sstore.SWFocusInput && focusVal != sstore.SWFocusCmd && focusVal != sstore.SWFocusCmdFg {
|
|
||||||
return nil, fmt.Errorf("/sw:set invalid focus argument %q, must be %s", focusVal, formatStrs([]string{sstore.SWFocusInput, sstore.SWFocusCmd, sstore.SWFocusCmdFg}, "or", false))
|
|
||||||
}
|
|
||||||
updateMap[sstore.SWField_Focus] = focusVal
|
|
||||||
setNonST = true
|
|
||||||
}
|
|
||||||
if pk.Kwargs["line"] != "" {
|
|
||||||
sw, err := sstore.GetScreenWindowByIds(ctx, ids.SessionId, ids.ScreenId, ids.WindowId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("/sw:set cannot get screen-window: %v", err)
|
|
||||||
}
|
|
||||||
var selectedLineStr string
|
|
||||||
if sw.SelectedLine > 0 {
|
|
||||||
selectedLineStr = strconv.Itoa(sw.SelectedLine)
|
|
||||||
}
|
|
||||||
ritem, err := resolveLine(ctx, ids.SessionId, ids.WindowId, pk.Kwargs["line"], selectedLineStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("/sw:set error resolving line: %v", err)
|
|
||||||
}
|
|
||||||
if ritem == nil {
|
|
||||||
return nil, fmt.Errorf("/sw:set could not resolve line %q", pk.Kwargs["line"])
|
|
||||||
}
|
|
||||||
setNonST = true
|
|
||||||
updateMap[sstore.SWField_SelectedLine] = ritem.Num
|
|
||||||
}
|
|
||||||
if len(updateMap) == 0 {
|
|
||||||
return nil, fmt.Errorf("/sw:set no updates, can set %s", formatStrs([]string{"line", "scrolltop", "focus"}, "or", false))
|
|
||||||
}
|
|
||||||
sw, err := sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("/sw:set failed to update: %v", err)
|
|
||||||
}
|
|
||||||
if !setNonST {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return sstore.ModelUpdate{ScreenWindows: []*sstore.ScreenWindowType{sw}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -669,7 +635,7 @@ func RemoteInstallCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RemoteInstallCancelCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteInstallCancelCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -683,7 +649,7 @@ func RemoteInstallCancelCommand(ctx context.Context, pk *scpacket.FeCommandPacke
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RemoteConnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteConnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -696,7 +662,7 @@ func RemoteConnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RemoteDisconnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteDisconnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -946,7 +912,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -976,7 +942,7 @@ func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RemoteShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1039,29 +1005,20 @@ func ScreenResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
screen, err := sstore.GetScreenById(ctx, ids.SessionId, ids.ScreenId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error retrieving screen: %v", err)
|
|
||||||
}
|
|
||||||
localRemote := remote.GetLocalRemote()
|
localRemote := remote.GetLocalRemote()
|
||||||
if localRemote == nil {
|
if localRemote == nil {
|
||||||
return nil, fmt.Errorf("error getting local remote (not found)")
|
return nil, fmt.Errorf("error getting local remote (not found)")
|
||||||
}
|
}
|
||||||
rptr := sstore.RemotePtrType{RemoteId: localRemote.RemoteId}
|
rptr := sstore.RemotePtrType{RemoteId: localRemote.RemoteId}
|
||||||
var windows []*sstore.WindowType
|
|
||||||
sessionUpdate := &sstore.SessionType{SessionId: ids.SessionId}
|
sessionUpdate := &sstore.SessionType{SessionId: ids.SessionId}
|
||||||
for _, sw := range screen.Windows {
|
ris, err := sstore.ScreenReset(ctx, ids.ScreenId)
|
||||||
ris, err := sstore.WindowReset(ctx, ids.SessionId, sw.WindowId)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, fmt.Errorf("error resetting screen window: %v", err)
|
||||||
return nil, fmt.Errorf("error resetting screen window: %v", err)
|
}
|
||||||
}
|
sessionUpdate.Remotes = append(sessionUpdate.Remotes, ris...)
|
||||||
sessionUpdate.Remotes = append(sessionUpdate.Remotes, ris...)
|
err = sstore.UpdateCurRemote(ctx, ids.ScreenId, rptr)
|
||||||
err = sstore.UpdateCurRemote(ctx, ids.SessionId, sw.WindowId, rptr)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, fmt.Errorf("cannot reset screen remote back to local: %w", err)
|
||||||
return nil, fmt.Errorf("cannot reset window remote back to local: %w", err)
|
|
||||||
}
|
|
||||||
winUpdate := &sstore.WindowType{SessionId: ids.SessionId, WindowId: sw.WindowId, CurRemote: rptr}
|
|
||||||
windows = append(windows, winUpdate)
|
|
||||||
}
|
}
|
||||||
outputStr := "reset screen state (all remote state reset)"
|
outputStr := "reset screen state (all remote state reset)"
|
||||||
cmd, err := makeStaticCmd(ctx, "screen:reset", ids, pk.GetRawStr(), []byte(outputStr))
|
cmd, err := makeStaticCmd(ctx, "screen:reset", ids, pk.GetRawStr(), []byte(outputStr))
|
||||||
@ -1075,13 +1032,12 @@ func ScreenResetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
update.Interactive = pk.Interactive
|
update.Interactive = pk.Interactive
|
||||||
update.Windows = windows
|
|
||||||
update.Sessions = []*sstore.SessionType{sessionUpdate}
|
update.Sessions = []*sstore.SessionType{sessionUpdate}
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1091,13 +1047,16 @@ func RemoteArchiveCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
|||||||
}
|
}
|
||||||
update := sstore.InfoMsgUpdate("remote [%s] archived", ids.Remote.DisplayName)
|
update := sstore.InfoMsgUpdate("remote [%s] archived", ids.Remote.DisplayName)
|
||||||
localRemote := remote.GetLocalRemote()
|
localRemote := remote.GetLocalRemote()
|
||||||
if localRemote != nil {
|
rptr := sstore.RemotePtrType{RemoteId: localRemote.GetRemoteId()}
|
||||||
update.Windows = []*sstore.WindowType{&sstore.WindowType{
|
err = sstore.UpdateCurRemote(ctx, ids.ScreenId, rptr)
|
||||||
SessionId: ids.SessionId,
|
if err != nil {
|
||||||
WindowId: ids.WindowId,
|
return nil, fmt.Errorf("cannot switch remote back to local: %w", err)
|
||||||
CurRemote: sstore.RemotePtrType{RemoteId: localRemote.GetRemoteId()},
|
|
||||||
}}
|
|
||||||
}
|
}
|
||||||
|
screen, err := sstore.GetScreenById(ctx, ids.ScreenId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot get updated screen: %w", err)
|
||||||
|
}
|
||||||
|
update.Screens = []*sstore.ScreenType{screen}
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1173,7 +1132,7 @@ func GetFullRemoteDisplayName(rptr *sstore.RemotePtrType, rstate *remote.RemoteR
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/%s error: %w", GetCmdStr(pk), err)
|
return nil, fmt.Errorf("/%s error: %w", GetCmdStr(pk), err)
|
||||||
}
|
}
|
||||||
@ -1191,7 +1150,7 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up
|
|||||||
if rstate.Archived {
|
if rstate.Archived {
|
||||||
return nil, fmt.Errorf("/%s error: remote %q cannot switch to archived remote", GetCmdStr(pk), newRemote)
|
return nil, fmt.Errorf("/%s error: remote %q cannot switch to archived remote", GetCmdStr(pk), newRemote)
|
||||||
}
|
}
|
||||||
err = sstore.UpdateCurRemote(ctx, ids.SessionId, ids.WindowId, *rptr)
|
err = sstore.UpdateCurRemote(ctx, ids.ScreenId, *rptr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/%s error: cannot update curremote: %w", GetCmdStr(pk), err)
|
return nil, fmt.Errorf("/%s error: cannot update curremote: %w", GetCmdStr(pk), err)
|
||||||
}
|
}
|
||||||
@ -1206,11 +1165,6 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up
|
|||||||
// TODO tricky error since the command was a success, but we can't show the output
|
// TODO tricky error since the command was a success, but we can't show the output
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
update.Windows = []*sstore.WindowType{&sstore.WindowType{
|
|
||||||
SessionId: ids.SessionId,
|
|
||||||
WindowId: ids.WindowId,
|
|
||||||
CurRemote: *rptr,
|
|
||||||
}}
|
|
||||||
update.Interactive = pk.Interactive
|
update.Interactive = pk.Interactive
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
@ -1252,27 +1206,27 @@ func addLineForCmd(ctx context.Context, metaCmd string, shouldFocus bool, ids re
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
sw, err := sstore.GetScreenWindowByIds(ctx, ids.SessionId, ids.ScreenId, ids.WindowId)
|
screen, err := sstore.GetScreenById(ctx, ids.ScreenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ignore error here, because the command has already run (nothing to do)
|
// ignore error here, because the command has already run (nothing to do)
|
||||||
log.Printf("%s error getting screen-window: %v\n", metaCmd, err)
|
log.Printf("%s error getting screen: %v\n", metaCmd, err)
|
||||||
}
|
}
|
||||||
if sw != nil {
|
if screen != nil {
|
||||||
updateMap := make(map[string]interface{})
|
updateMap := make(map[string]interface{})
|
||||||
updateMap[sstore.SWField_SelectedLine] = rtnLine.LineNum
|
updateMap[sstore.ScreenField_SelectedLine] = rtnLine.LineNum
|
||||||
if shouldFocus {
|
if shouldFocus {
|
||||||
updateMap[sstore.SWField_Focus] = sstore.SWFocusCmdFg
|
updateMap[sstore.ScreenField_Focus] = sstore.ScreenFocusCmdFg
|
||||||
}
|
}
|
||||||
sw, err = sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
|
screen, err = sstore.UpdateScreen(ctx, ids.ScreenId, updateMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ignore error again (nothing to do)
|
// ignore error again (nothing to do)
|
||||||
log.Printf("%s error updating screen-window selected line: %v\n", metaCmd, err)
|
log.Printf("%s error updating screen selected line: %v\n", metaCmd, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update := &sstore.ModelUpdate{
|
update := &sstore.ModelUpdate{
|
||||||
Line: rtnLine,
|
Line: rtnLine,
|
||||||
Cmd: cmd,
|
Cmd: cmd,
|
||||||
ScreenWindows: []*sstore.ScreenWindowType{sw},
|
Screens: []*sstore.ScreenType{screen},
|
||||||
}
|
}
|
||||||
updateHistoryContext(ctx, rtnLine, cmd)
|
updateHistoryContext(ctx, rtnLine, cmd)
|
||||||
return update, nil
|
return update, nil
|
||||||
@ -1374,7 +1328,7 @@ func doCompGen(ctx context.Context, pk *scpacket.FeCommandPacketType, prefix str
|
|||||||
if !packet.IsValidCompGenType(compType) {
|
if !packet.IsValidCompGenType(compType) {
|
||||||
return nil, false, fmt.Errorf("/_compgen invalid type '%s'", compType)
|
return nil, false, fmt.Errorf("/_compgen invalid type '%s'", compType)
|
||||||
}
|
}
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_RemoteConnected)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window|R_RemoteConnected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("/_compgen error: %w", err)
|
return nil, false, fmt.Errorf("/_compgen error: %w", err)
|
||||||
}
|
}
|
||||||
@ -1447,7 +1401,7 @@ func CompGenCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window)
|
ids, err := resolveUiIds(ctx, pk, R_Session|R_Screen|R_Window)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/comment error: %w", err)
|
return nil, fmt.Errorf("/comment error: %w", err)
|
||||||
}
|
}
|
||||||
@ -1461,14 +1415,14 @@ func CommentCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
|||||||
}
|
}
|
||||||
updateHistoryContext(ctx, rtnLine, nil)
|
updateHistoryContext(ctx, rtnLine, nil)
|
||||||
updateMap := make(map[string]interface{})
|
updateMap := make(map[string]interface{})
|
||||||
updateMap[sstore.SWField_SelectedLine] = rtnLine.LineNum
|
updateMap[sstore.ScreenField_SelectedLine] = rtnLine.LineNum
|
||||||
updateMap[sstore.SWField_Focus] = sstore.SWFocusInput
|
updateMap[sstore.ScreenField_Focus] = sstore.ScreenFocusInput
|
||||||
sw, err := sstore.UpdateScreenWindow(ctx, ids.SessionId, ids.ScreenId, ids.WindowId, updateMap)
|
screen, err := sstore.UpdateScreen(ctx, ids.ScreenId, updateMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ignore error again (nothing to do)
|
// ignore error again (nothing to do)
|
||||||
log.Printf("/comment error updating screen-window selected line: %v\n", err)
|
log.Printf("/comment error updating screen-window selected line: %v\n", err)
|
||||||
}
|
}
|
||||||
update := sstore.ModelUpdate{Line: rtnLine, ScreenWindows: []*sstore.ScreenWindowType{sw}}
|
update := sstore.ModelUpdate{Line: rtnLine, Screens: []*sstore.ScreenType{screen}}
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1809,22 +1763,22 @@ func ClearCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if resolveBool(pk.Kwargs["purge"], false) {
|
if resolveBool(pk.Kwargs["purge"], false) {
|
||||||
update, err := sstore.PurgeWindowLines(ctx, ids.SessionId, ids.WindowId)
|
update, err := sstore.PurgeScreenLines(ctx, ids.ScreenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("clearing window: %v", err)
|
return nil, fmt.Errorf("clearing screen: %v", err)
|
||||||
}
|
}
|
||||||
update.Info = &sstore.InfoMsgType{
|
update.Info = &sstore.InfoMsgType{
|
||||||
InfoMsg: fmt.Sprintf("window cleared (all lines purged)"),
|
InfoMsg: fmt.Sprintf("screen cleared (all lines purged)"),
|
||||||
TimeoutMs: 2000,
|
TimeoutMs: 2000,
|
||||||
}
|
}
|
||||||
return update, nil
|
return update, nil
|
||||||
} else {
|
} else {
|
||||||
update, err := sstore.ArchiveWindowLines(ctx, ids.SessionId, ids.WindowId)
|
update, err := sstore.ArchiveScreenLines(ctx, ids.ScreenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("clearing window: %v", err)
|
return nil, fmt.Errorf("clearing screen: %v", err)
|
||||||
}
|
}
|
||||||
update.Info = &sstore.InfoMsgType{
|
update.Info = &sstore.InfoMsgType{
|
||||||
InfoMsg: fmt.Sprintf("window cleared"),
|
InfoMsg: fmt.Sprintf("screen cleared"),
|
||||||
TimeoutMs: 2000,
|
TimeoutMs: 2000,
|
||||||
}
|
}
|
||||||
return update, nil
|
return update, nil
|
||||||
@ -2121,11 +2075,11 @@ func LineViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/line:view invalid screen arg: %v", err)
|
return nil, fmt.Errorf("/line:view invalid screen arg: %v", err)
|
||||||
}
|
}
|
||||||
screen, err := sstore.GetScreenById(ctx, sessionId, screenRItem.Id)
|
screen, err := sstore.GetScreenById(ctx, screenRItem.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/line:view could not get screen: %v", err)
|
return nil, fmt.Errorf("/line:view could not get screen: %v", err)
|
||||||
}
|
}
|
||||||
lineRItem, err := resolveLine(ctx, sessionId, screen.ActiveWindowId, lineArg, "")
|
lineRItem, err := resolveLine(ctx, sessionId, screen.WindowId, lineArg, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("/line:view invalid line arg: %v", err)
|
return nil, fmt.Errorf("/line:view invalid line arg: %v", err)
|
||||||
}
|
}
|
||||||
@ -2134,14 +2088,14 @@ func LineViewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
updateMap := make(map[string]interface{})
|
updateMap := make(map[string]interface{})
|
||||||
updateMap[sstore.SWField_SelectedLine] = lineRItem.Num
|
updateMap[sstore.ScreenField_SelectedLine] = lineRItem.Num
|
||||||
updateMap[sstore.SWField_AnchorLine] = lineRItem.Num
|
updateMap[sstore.ScreenField_AnchorLine] = lineRItem.Num
|
||||||
updateMap[sstore.SWField_AnchorOffset] = 0
|
updateMap[sstore.ScreenField_AnchorOffset] = 0
|
||||||
sw, err := sstore.UpdateScreenWindow(ctx, sessionId, screenRItem.Id, screen.ActiveWindowId, updateMap)
|
screen, err = sstore.UpdateScreen(ctx, screenRItem.Id, updateMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
update.ScreenWindows = []*sstore.ScreenWindowType{sw}
|
update.Screens = []*sstore.ScreenType{screen}
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
pkg/mapqueue/mapqueue.go
Normal file
99
pkg/mapqueue/mapqueue.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package mapqueue
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"runtime/debug"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MQEntry struct {
|
||||||
|
Lock *sync.Mutex
|
||||||
|
Running bool
|
||||||
|
Queue chan func()
|
||||||
|
}
|
||||||
|
|
||||||
|
type MapQueue struct {
|
||||||
|
Lock *sync.Mutex
|
||||||
|
M map[string]*MQEntry
|
||||||
|
QueueSize int
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeMapQueue(queueSize int) *MapQueue {
|
||||||
|
rtn := &MapQueue{
|
||||||
|
Lock: &sync.Mutex{},
|
||||||
|
M: make(map[string]*MQEntry),
|
||||||
|
QueueSize: queueSize,
|
||||||
|
}
|
||||||
|
return rtn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mq *MapQueue) getEntry(id string) *MQEntry {
|
||||||
|
mq.Lock.Lock()
|
||||||
|
defer mq.Lock.Unlock()
|
||||||
|
entry := mq.M[id]
|
||||||
|
if entry == nil {
|
||||||
|
entry = &MQEntry{
|
||||||
|
Lock: &sync.Mutex{},
|
||||||
|
Running: false,
|
||||||
|
Queue: make(chan func(), mq.QueueSize),
|
||||||
|
}
|
||||||
|
mq.M[id] = entry
|
||||||
|
}
|
||||||
|
return entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *MQEntry) add(fn func()) error {
|
||||||
|
select {
|
||||||
|
case entry.Queue <- fn:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("input queue full")
|
||||||
|
}
|
||||||
|
entry.tryRun()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runFn(fn func()) {
|
||||||
|
defer func() {
|
||||||
|
r := recover()
|
||||||
|
if r == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("[error] panic in MQEntry runFn: %v\n", r)
|
||||||
|
debug.PrintStack()
|
||||||
|
return
|
||||||
|
}()
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *MQEntry) tryRun() {
|
||||||
|
entry.Lock.Lock()
|
||||||
|
defer entry.Lock.Unlock()
|
||||||
|
if entry.Running {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(entry.Queue) > 0 {
|
||||||
|
entry.Running = true
|
||||||
|
go entry.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (entry *MQEntry) run() {
|
||||||
|
for fn := range entry.Queue {
|
||||||
|
runFn(fn)
|
||||||
|
}
|
||||||
|
entry.Lock.Lock()
|
||||||
|
entry.Running = false
|
||||||
|
entry.Lock.Unlock()
|
||||||
|
entry.tryRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mq *MapQueue) Enqueue(id string, fn func()) error {
|
||||||
|
entry := mq.getEntry(id)
|
||||||
|
err := entry.add(fn)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot enqueue: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -1499,12 +1499,12 @@ func (msh *MShellProc) handleCmdDonePacket(donePk *packet.CmdDonePacketType) {
|
|||||||
msh.WriteToPtyBuffer("*error updating cmddone: %v\n", err)
|
msh.WriteToPtyBuffer("*error updating cmddone: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sws, err := sstore.UpdateSWsWithCmdFg(context.Background(), donePk.CK.GetSessionId(), donePk.CK.GetCmdId())
|
screens, err := sstore.UpdateScreensWithCmdFg(context.Background(), donePk.CK.GetSessionId(), donePk.CK.GetCmdId())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msh.WriteToPtyBuffer("*error trying to update cmd-fg screen windows: %v\n", err)
|
msh.WriteToPtyBuffer("*error trying to update cmd-fg screen windows: %v\n", err)
|
||||||
// fall-through (nothing to do)
|
// fall-through (nothing to do)
|
||||||
}
|
}
|
||||||
update.ScreenWindows = sws
|
update.Screens = screens
|
||||||
rct := msh.GetRunningCmd(donePk.CK)
|
rct := msh.GetRunningCmd(donePk.CK)
|
||||||
var statePtr *sstore.ShellStatePtr
|
var statePtr *sstore.ShellStatePtr
|
||||||
if donePk.FinalState != nil && rct != nil {
|
if donePk.FinalState != nil && rct != nil {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/scripthaus-dev/mshell/pkg/packet"
|
"github.com/scripthaus-dev/mshell/pkg/packet"
|
||||||
|
"github.com/scripthaus-dev/sh2-server/pkg/mapqueue"
|
||||||
"github.com/scripthaus-dev/sh2-server/pkg/remote"
|
"github.com/scripthaus-dev/sh2-server/pkg/remote"
|
||||||
"github.com/scripthaus-dev/sh2-server/pkg/scpacket"
|
"github.com/scripthaus-dev/sh2-server/pkg/scpacket"
|
||||||
"github.com/scripthaus-dev/sh2-server/pkg/sstore"
|
"github.com/scripthaus-dev/sh2-server/pkg/sstore"
|
||||||
@ -17,6 +18,13 @@ import (
|
|||||||
|
|
||||||
const WSStatePacketChSize = 20
|
const WSStatePacketChSize = 20
|
||||||
const MaxInputDataSize = 1000
|
const MaxInputDataSize = 1000
|
||||||
|
const RemoteInputQueueSize = 100
|
||||||
|
|
||||||
|
var RemoteInputMapQueue *mapqueue.MapQueue
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RemoteInputMapQueue = mapqueue.MakeMapQueue(RemoteInputQueueSize)
|
||||||
|
}
|
||||||
|
|
||||||
type WSState struct {
|
type WSState struct {
|
||||||
Lock *sync.Mutex
|
Lock *sync.Mutex
|
||||||
@ -227,13 +235,16 @@ func (ws *WSState) RunWSRead() {
|
|||||||
log.Printf("[error] invalid input packet, remoteid is not set\n")
|
log.Printf("[error] invalid input packet, remoteid is not set\n")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go func() {
|
err := RemoteInputMapQueue.Enqueue(feInputPk.Remote.RemoteId, func() {
|
||||||
// TODO enforce a strong ordering (channel with list)
|
|
||||||
err = sendCmdInput(feInputPk)
|
err = sendCmdInput(feInputPk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[error] sending command input: %v\n", err)
|
log.Printf("[error] sending command input: %v\n", err)
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[error] could not queue sendCmdInput: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if pk.GetType() == scpacket.RemoteInputPacketStr {
|
if pk.GetType() == scpacket.RemoteInputPacketStr {
|
||||||
|
@ -405,9 +405,8 @@ func GetAllSessions(ctx context.Context) (*ModelUpdate, error) {
|
|||||||
sessionMap[session.SessionId] = session
|
sessionMap[session.SessionId] = session
|
||||||
session.Full = true
|
session.Full = true
|
||||||
}
|
}
|
||||||
var screens []*ScreenType
|
|
||||||
query = `SELECT * FROM screen ORDER BY archived, screenidx, archivedts`
|
query = `SELECT * FROM screen ORDER BY archived, screenidx, archivedts`
|
||||||
tx.Select(&screens, query)
|
screens := SelectMapsGen[*ScreenType](tx, query)
|
||||||
screenMap := make(map[string][]*ScreenType)
|
screenMap := make(map[string][]*ScreenType)
|
||||||
for _, screen := range screens {
|
for _, screen := range screens {
|
||||||
screenArr := screenMap[screen.SessionId]
|
screenArr := screenMap[screen.SessionId]
|
||||||
@ -417,20 +416,6 @@ func GetAllSessions(ctx context.Context) (*ModelUpdate, error) {
|
|||||||
for _, session := range rtn {
|
for _, session := range rtn {
|
||||||
session.Screens = screenMap[session.SessionId]
|
session.Screens = screenMap[session.SessionId]
|
||||||
}
|
}
|
||||||
var sws []*ScreenWindowType
|
|
||||||
query = `SELECT * FROM screen_window`
|
|
||||||
tx.Select(&sws, query)
|
|
||||||
screenIdMap := make(map[string]*ScreenType)
|
|
||||||
for _, screen := range screens {
|
|
||||||
screenIdMap[screen.SessionId+screen.ScreenId] = screen
|
|
||||||
}
|
|
||||||
for _, sw := range sws {
|
|
||||||
screen := screenIdMap[sw.SessionId+sw.ScreenId]
|
|
||||||
if screen == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
screen.Windows = append(screen.Windows, sw)
|
|
||||||
}
|
|
||||||
query = `SELECT * FROM remote_instance`
|
query = `SELECT * FROM remote_instance`
|
||||||
riArr := SelectMapsGen[*RemoteInstance](tx, query)
|
riArr := SelectMapsGen[*RemoteInstance](tx, query)
|
||||||
for _, ri := range riArr {
|
for _, ri := range riArr {
|
||||||
@ -449,22 +434,20 @@ func GetAllSessions(ctx context.Context) (*ModelUpdate, error) {
|
|||||||
return &ModelUpdate{Sessions: rtn, ActiveSessionId: activeSessionId}, nil
|
return &ModelUpdate{Sessions: rtn, ActiveSessionId: activeSessionId}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetWindowById(ctx context.Context, sessionId string, windowId string) (*WindowType, error) {
|
func GetFullScreenById(ctx context.Context, screenId string) (*ScreenType, error) {
|
||||||
var rtnWindow *WindowType
|
return WithTxRtn(ctx, func(tx *TxWrap) (*ScreenType, error) {
|
||||||
err := WithTx(ctx, func(tx *TxWrap) error {
|
query := `SELECT * FROM screen WHERE screenid = ?`
|
||||||
query := `SELECT * FROM window WHERE sessionid = ? AND windowid = ?`
|
screen := GetMapGen[*ScreenType](tx, query, screenId)
|
||||||
m := tx.GetMap(query, sessionId, windowId)
|
if screen == nil {
|
||||||
if m == nil {
|
return nil, nil
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
rtnWindow = FromMap[*WindowType](m)
|
|
||||||
query = `SELECT * FROM line WHERE sessionid = ? AND windowid = ? ORDER BY linenum`
|
query = `SELECT * FROM line WHERE sessionid = ? AND windowid = ? ORDER BY linenum`
|
||||||
tx.Select(&rtnWindow.Lines, query, sessionId, windowId)
|
tx.Select(&screen.Lines, query, screen.SessionId, screen.WindowId)
|
||||||
query = `SELECT * FROM cmd WHERE cmdid IN (SELECT cmdid FROM line WHERE sessionid = ? AND windowid = ?)`
|
query = `SELECT * FROM cmd WHERE cmdid IN (SELECT cmdid FROM line WHERE sessionid = ? AND windowid = ?)`
|
||||||
rtnWindow.Cmds = SelectMapsGen[*CmdType](tx, query, sessionId, windowId)
|
screen.Cmds = SelectMapsGen[*CmdType](tx, query, screen.SessionId, screen.WindowId)
|
||||||
return nil
|
screen.Full = true
|
||||||
|
return screen, nil
|
||||||
})
|
})
|
||||||
return rtnWindow, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// includes archived screens (does not include screen windows)
|
// includes archived screens (does not include screen windows)
|
||||||
@ -649,11 +632,11 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
|||||||
if !tx.Exists(query, sessionId) {
|
if !tx.Exists(query, sessionId) {
|
||||||
return fmt.Errorf("cannot create screen, no session found (or session archived)")
|
return fmt.Errorf("cannot create screen, no session found (or session archived)")
|
||||||
}
|
}
|
||||||
remoteId := tx.GetString(`SELECT remoteid FROM remote WHERE remotealias = ?`, LocalRemoteAlias)
|
localRemoteId := tx.GetString(`SELECT remoteid FROM remote WHERE remotealias = ?`, LocalRemoteAlias)
|
||||||
if remoteId == "" {
|
if localRemoteId == "" {
|
||||||
return fmt.Errorf("cannot create screen, no local remote found")
|
return fmt.Errorf("cannot create screen, no local remote found")
|
||||||
}
|
}
|
||||||
newWindowId := txCreateWindow(tx, sessionId, RemotePtrType{RemoteId: remoteId})
|
newWindowId := scbase.GenPromptUUID()
|
||||||
maxScreenIdx := tx.GetInt(`SELECT COALESCE(max(screenidx), 0) FROM screen WHERE sessionid = ? AND NOT archived`, sessionId)
|
maxScreenIdx := tx.GetInt(`SELECT COALESCE(max(screenidx), 0) FROM screen WHERE sessionid = ? AND NOT archived`, sessionId)
|
||||||
var screenName string
|
var screenName string
|
||||||
if origScreenName == "" {
|
if origScreenName == "" {
|
||||||
@ -663,11 +646,25 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
|||||||
screenName = origScreenName
|
screenName = origScreenName
|
||||||
}
|
}
|
||||||
newScreenId = scbase.GenPromptUUID()
|
newScreenId = scbase.GenPromptUUID()
|
||||||
query = `INSERT INTO screen (sessionid, screenid, name, activewindowid, screenidx, screenopts, ownerid, sharemode, incognito, archived, archivedts) VALUES (?, ?, ?, ?, ?, ?, '', 'local', 0, 0, 0)`
|
screen := &ScreenType{
|
||||||
tx.Exec(query, sessionId, newScreenId, screenName, newWindowId, maxScreenIdx+1, ScreenOptsType{})
|
SessionId: sessionId,
|
||||||
layout := LayoutType{Type: LayoutFull}
|
ScreenId: newScreenId,
|
||||||
query = `INSERT INTO screen_window (sessionid, screenid, windowid, name, layout, selectedline, anchor, focustype) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
WindowId: newWindowId,
|
||||||
tx.Exec(query, sessionId, newScreenId, newWindowId, DefaultScreenWindowName, layout, 0, SWAnchorType{}, "input")
|
Name: screenName,
|
||||||
|
ScreenIdx: int64(maxScreenIdx) + 1,
|
||||||
|
ScreenOpts: ScreenOptsType{},
|
||||||
|
OwnerId: "",
|
||||||
|
ShareMode: ShareModeLocal,
|
||||||
|
CurRemote: RemotePtrType{RemoteId: localRemoteId},
|
||||||
|
NextLineNum: 1,
|
||||||
|
SelectedLine: 0,
|
||||||
|
Anchor: ScreenAnchorType{},
|
||||||
|
FocusType: ScreenFocusInput,
|
||||||
|
Archived: false,
|
||||||
|
ArchivedTs: 0,
|
||||||
|
}
|
||||||
|
query = `INSERT INTO screen (sessionid, screenid, windowid, name, screenidx, screenopts, ownerid, sharemode, curremoteownerid, curremoteid, curremotename, nextlinenum, selectedline, anchor, focustype, archived, archivedts) VALUES (:sessionid,:screenid,:windowid,:name,:screenidx,:screenopts,:ownerid,:sharemode,:curremoteownerid,:curremoteid,:curremotename,:nextlinenum,:selectedline,:anchor,:focustype,:archived,:archivedts)`
|
||||||
|
tx.NamedExec(query, screen.ToMap())
|
||||||
if activate {
|
if activate {
|
||||||
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
|
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
|
||||||
tx.Exec(query, newScreenId, sessionId)
|
tx.Exec(query, newScreenId, sessionId)
|
||||||
@ -677,7 +674,7 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
|||||||
if txErr != nil {
|
if txErr != nil {
|
||||||
return nil, txErr
|
return nil, txErr
|
||||||
}
|
}
|
||||||
newScreen, err := GetScreenById(ctx, sessionId, newScreenId)
|
newScreen, err := GetScreenById(ctx, newScreenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -689,42 +686,12 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
|||||||
return ModelUpdate{Sessions: []*SessionType{bareSession}}, nil
|
return ModelUpdate{Sessions: []*SessionType{bareSession}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetScreenById(ctx context.Context, sessionId string, screenId string) (*ScreenType, error) {
|
func GetScreenById(ctx context.Context, screenId string) (*ScreenType, error) {
|
||||||
var rtnScreen *ScreenType
|
return WithTxRtn(ctx, func(tx *TxWrap) (*ScreenType, error) {
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
query := `SELECT * FROM screen WHERE screenid = ?`
|
||||||
query := `SELECT * FROM screen WHERE sessionid = ? AND screenid = ?`
|
screen := GetMapGen[*ScreenType](tx, query, screenId)
|
||||||
var screen ScreenType
|
return screen, nil
|
||||||
found := tx.Get(&screen, query, sessionId, screenId)
|
|
||||||
if !found {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rtnScreen = &screen
|
|
||||||
query = `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ?`
|
|
||||||
tx.Select(&screen.Windows, query, sessionId, screenId)
|
|
||||||
screen.Full = true
|
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
if txErr != nil {
|
|
||||||
return nil, txErr
|
|
||||||
}
|
|
||||||
return rtnScreen, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func txCreateWindow(tx *TxWrap, sessionId string, curRemote RemotePtrType) string {
|
|
||||||
w := &WindowType{
|
|
||||||
SessionId: sessionId,
|
|
||||||
WindowId: scbase.GenPromptUUID(),
|
|
||||||
CurRemote: curRemote,
|
|
||||||
NextLineNum: 1,
|
|
||||||
WinOpts: WindowOptsType{},
|
|
||||||
ShareMode: ShareModeLocal,
|
|
||||||
ShareOpts: WindowShareOptsType{},
|
|
||||||
}
|
|
||||||
wmap := w.ToMap()
|
|
||||||
query := `INSERT INTO window ( sessionid, windowid, curremoteownerid, curremoteid, curremotename, nextlinenum, winopts, ownerid, sharemode, shareopts)
|
|
||||||
VALUES (:sessionid,:windowid,:curremoteownerid,:curremoteid,:curremotename,:nextlinenum,:winopts,:ownerid,:sharemode,:shareopts)`
|
|
||||||
tx.NamedExec(query, wmap)
|
|
||||||
return w.WindowId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindLineIdByArg(ctx context.Context, sessionId string, windowId string, lineArg string) (string, error) {
|
func FindLineIdByArg(ctx context.Context, sessionId string, windowId string, lineArg string) (string, error) {
|
||||||
@ -1071,7 +1038,7 @@ func ArchiveScreen(ctx context.Context, sessionId string, screenId string) (Upda
|
|||||||
return nil, txErr
|
return nil, txErr
|
||||||
}
|
}
|
||||||
update := ModelUpdate{Sessions: []*SessionType{bareSession}}
|
update := ModelUpdate{Sessions: []*SessionType{bareSession}}
|
||||||
newScreen, _ := GetScreenById(ctx, sessionId, screenId)
|
newScreen, _ := GetScreenById(ctx, screenId)
|
||||||
if newScreen != nil {
|
if newScreen != nil {
|
||||||
bareSession.Screens = append(bareSession.Screens, newScreen)
|
bareSession.Screens = append(bareSession.Screens, newScreen)
|
||||||
}
|
}
|
||||||
@ -1264,17 +1231,16 @@ func UpdateRemoteState(ctx context.Context, sessionId string, windowId string, r
|
|||||||
return ri, txErr
|
return ri, txErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateCurRemote(ctx context.Context, sessionId string, windowId string, remotePtr RemotePtrType) error {
|
func UpdateCurRemote(ctx context.Context, screenId string, remotePtr RemotePtrType) error {
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
return WithTx(ctx, func(tx *TxWrap) error {
|
||||||
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
query := `SELECT screenid FROM screen WHERE screenid = ?`
|
||||||
if !tx.Exists(query, sessionId, windowId) {
|
if !tx.Exists(query, screenId) {
|
||||||
return fmt.Errorf("cannot update curremote: no window found")
|
return fmt.Errorf("cannot update curremote: no screen found")
|
||||||
}
|
}
|
||||||
query = `UPDATE window SET curremoteownerid = ?, curremoteid = ?, curremotename = ? WHERE sessionid = ? AND windowid = ?`
|
query = `UPDATE screen SET curremoteownerid = ?, curremoteid = ?, curremotename = ? WHERE screenid = ?`
|
||||||
tx.Exec(query, remotePtr.OwnerId, remotePtr.RemoteId, remotePtr.Name, sessionId, windowId)
|
tx.Exec(query, remotePtr.OwnerId, remotePtr.RemoteId, remotePtr.Name, screenId)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return txErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func reorderStrings(strs []string, toMove string, newIndex int) []string {
|
func reorderStrings(strs []string, toMove string, newIndex int) []string {
|
||||||
@ -1353,77 +1319,65 @@ func SetScreenName(ctx context.Context, sessionId string, screenId string, name
|
|||||||
return txErr
|
return txErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetScreenOpts(ctx context.Context, sessionId string, screenId string, opts *ScreenOptsType) error {
|
func ArchiveScreenLines(ctx context.Context, screenId string) (*ModelUpdate, error) {
|
||||||
if opts == nil {
|
|
||||||
return fmt.Errorf("invalid screen opts cannot be nil")
|
|
||||||
}
|
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||||
query := `SELECT screenid FROM screen WHERE sessionid = ? AND screenid = ?`
|
query := `SELECT sessionid, windowid FROM screen WHERE screenid = ?`
|
||||||
if !tx.Exists(query, sessionId, screenId) {
|
var swkeys SWKeys
|
||||||
return fmt.Errorf("screen does not exist")
|
tx.Get(&swkeys, query, screenId)
|
||||||
}
|
if swkeys.SessionId == "" || swkeys.WindowId == "" {
|
||||||
query = `UPDATE screen SET screenopts = ? WHERE sessionid = ? AND screenid = ?`
|
return fmt.Errorf("screen windowid does not exist")
|
||||||
tx.Exec(query, opts, sessionId, screenId)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return txErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func ArchiveWindowLines(ctx context.Context, sessionId string, windowId string) (*ModelUpdate, error) {
|
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
||||||
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
|
||||||
if !tx.Exists(query, sessionId, windowId) {
|
|
||||||
return fmt.Errorf("window does not exist")
|
|
||||||
}
|
}
|
||||||
query = `UPDATE line SET archived = 1 WHERE sessionid = ? AND windowid = ?`
|
query = `UPDATE line SET archived = 1 WHERE sessionid = ? AND windowid = ?`
|
||||||
tx.Exec(query, sessionId, windowId)
|
tx.Exec(query, swkeys.SessionId, swkeys.WindowId)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if txErr != nil {
|
if txErr != nil {
|
||||||
return nil, txErr
|
return nil, txErr
|
||||||
}
|
}
|
||||||
win, err := GetWindowById(ctx, sessionId, windowId)
|
screen, err := GetFullScreenById(ctx, screenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ModelUpdate{Windows: []*WindowType{win}}, nil
|
return &ModelUpdate{Screens: []*ScreenType{screen}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func PurgeWindowLines(ctx context.Context, sessionId string, windowId string) (*ModelUpdate, error) {
|
func PurgeScreenLines(ctx context.Context, screenId string) (*ModelUpdate, error) {
|
||||||
var lineIds []string
|
var lineIds []string
|
||||||
|
var swkeys SWKeys
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||||
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
query := `SELECT sessionid, windowid FROM screen WHERE screenid = ?`
|
||||||
if !tx.Exists(query, sessionId, windowId) {
|
tx.Get(&swkeys, query, screenId)
|
||||||
return fmt.Errorf("window does not exist")
|
if swkeys.SessionId == "" || swkeys.WindowId == "" {
|
||||||
|
return fmt.Errorf("screen windowid does not exist")
|
||||||
}
|
}
|
||||||
query = `SELECT lineid FROM line WHERE sessionid = ? AND windowid = ?`
|
query = `SELECT lineid FROM line WHERE sessionid = ? AND windowid = ?`
|
||||||
lineIds = tx.SelectStrings(query, sessionId, windowId)
|
lineIds = tx.SelectStrings(query, swkeys.SessionId, swkeys.WindowId)
|
||||||
query = `DELETE FROM line WHERE sessionid = ? AND windowid = ?`
|
query = `DELETE FROM line WHERE sessionid = ? AND windowid = ?`
|
||||||
tx.Exec(query, sessionId, windowId)
|
tx.Exec(query, swkeys.SessionId, swkeys.WindowId)
|
||||||
query = `DELETE FROM history WHERE sessionid = ? AND windowid = ?`
|
query = `DELETE FROM history WHERE sessionid = ? AND windowid = ?`
|
||||||
tx.Exec(query, sessionId, windowId)
|
tx.Exec(query, swkeys.SessionId, swkeys.WindowId)
|
||||||
query = `UPDATE window SET nextlinenum = 1 WHERE sessionid = ? AND windowid = ?`
|
query = `UPDATE screen SET nextlinenum = 1 WHERE screenid = ?`
|
||||||
tx.Exec(query, sessionId, windowId)
|
tx.Exec(query, screenId)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if txErr != nil {
|
if txErr != nil {
|
||||||
return nil, txErr
|
return nil, txErr
|
||||||
}
|
}
|
||||||
go cleanSessionCmds(context.Background(), sessionId)
|
go cleanSessionCmds(context.Background(), swkeys.SessionId)
|
||||||
win, err := GetWindowById(ctx, sessionId, windowId)
|
screen, err := GetFullScreenById(ctx, screenId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, lineId := range lineIds {
|
for _, lineId := range lineIds {
|
||||||
line := &LineType{
|
line := &LineType{
|
||||||
SessionId: sessionId,
|
SessionId: swkeys.SessionId,
|
||||||
WindowId: windowId,
|
WindowId: swkeys.WindowId,
|
||||||
LineId: lineId,
|
LineId: lineId,
|
||||||
Remove: true,
|
Remove: true,
|
||||||
}
|
}
|
||||||
win.Lines = append(win.Lines, line)
|
screen.Lines = append(screen.Lines, line)
|
||||||
}
|
}
|
||||||
return &ModelUpdate{Windows: []*WindowType{win}}, nil
|
return &ModelUpdate{Screens: []*ScreenType{screen}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRunningWindowCmds(ctx context.Context, sessionId string, windowId string) ([]*CmdType, error) {
|
func GetRunningWindowCmds(ctx context.Context, sessionId string, windowId string) ([]*CmdType, error) {
|
||||||
@ -1449,24 +1403,25 @@ func UpdateCmdTermOpts(ctx context.Context, sessionId string, cmdId string, term
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns riids of deleted RIs
|
// returns riids of deleted RIs
|
||||||
func WindowReset(ctx context.Context, sessionId string, windowId string) ([]*RemoteInstance, error) {
|
func ScreenReset(ctx context.Context, screenId string) ([]*RemoteInstance, error) {
|
||||||
var delRis []*RemoteInstance
|
return WithTxRtn(ctx, func(tx *TxWrap) ([]*RemoteInstance, error) {
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
var swkeys SWKeys
|
||||||
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
query := `SELECT sessionid, windowid FROM screen WHERE screenid = ?`
|
||||||
if !tx.Exists(query, sessionId, windowId) {
|
tx.Get(&swkeys, query, screenId)
|
||||||
return fmt.Errorf("window does not exist")
|
if swkeys.SessionId == "" || swkeys.WindowId == "" {
|
||||||
|
return nil, fmt.Errorf("screen does not exist")
|
||||||
}
|
}
|
||||||
query = `SELECT riid FROM remote_instance WHERE sessionid = ? AND windowid = ?`
|
query = `SELECT riid FROM remote_instance WHERE sessionid = ? AND windowid = ?`
|
||||||
riids := tx.SelectStrings(query, sessionId, windowId)
|
riids := tx.SelectStrings(query, swkeys.SessionId, swkeys.WindowId)
|
||||||
|
var delRis []*RemoteInstance
|
||||||
for _, riid := range riids {
|
for _, riid := range riids {
|
||||||
ri := &RemoteInstance{SessionId: sessionId, WindowId: windowId, RIId: riid, Remove: true}
|
ri := &RemoteInstance{SessionId: swkeys.SessionId, WindowId: swkeys.WindowId, RIId: riid, Remove: true}
|
||||||
delRis = append(delRis, ri)
|
delRis = append(delRis, ri)
|
||||||
}
|
}
|
||||||
query = `DELETE FROM remote_instance WHERE sessionid = ? AND windowid = ?`
|
query = `DELETE FROM remote_instance WHERE sessionid = ? AND windowid = ?`
|
||||||
tx.Exec(query, sessionId, windowId)
|
tx.Exec(query, swkeys.SessionId, swkeys.WindowId)
|
||||||
return nil
|
return delRis, nil
|
||||||
})
|
})
|
||||||
return delRis, txErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error) {
|
func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error) {
|
||||||
@ -1480,10 +1435,6 @@ func DeleteSession(ctx context.Context, sessionId string) (UpdatePacket, error)
|
|||||||
tx.Exec(query, sessionId)
|
tx.Exec(query, sessionId)
|
||||||
query = `DELETE FROM screen WHERE sessionid = ?`
|
query = `DELETE FROM screen WHERE sessionid = ?`
|
||||||
tx.Exec(query, sessionId)
|
tx.Exec(query, sessionId)
|
||||||
query = `DELETE FROM screen_window WHERE sessionid = ?`
|
|
||||||
tx.Exec(query, sessionId)
|
|
||||||
query = `DELETE FROM window WHERE sessionid = ?`
|
|
||||||
tx.Exec(query, sessionId)
|
|
||||||
query = `DELETE FROM history WHERE sessionid = ?`
|
query = `DELETE FROM history WHERE sessionid = ?`
|
||||||
tx.Exec(query, sessionId)
|
tx.Exec(query, sessionId)
|
||||||
query = `DELETE FROM line WHERE sessionid = ?`
|
query = `DELETE FROM line WHERE sessionid = ?`
|
||||||
@ -1693,64 +1644,55 @@ func UpdateRemote(ctx context.Context, remoteId string, editMap map[string]inter
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SWField_AnchorLine = "anchorline" // int
|
ScreenField_AnchorLine = "anchorline" // int
|
||||||
SWField_AnchorOffset = "anchoroffset" // int
|
ScreenField_AnchorOffset = "anchoroffset" // int
|
||||||
SWField_SelectedLine = "selectedline" // int
|
ScreenField_SelectedLine = "selectedline" // int
|
||||||
SWField_Focus = "focustype" // string
|
ScreenField_Focus = "focustype" // string
|
||||||
|
ScreenField_TabColor = "tabcolor" // string
|
||||||
|
ScreenField_PTerm = "pterm" // string
|
||||||
|
ScreenField_Name = "name" // string
|
||||||
)
|
)
|
||||||
|
|
||||||
func UpdateScreenWindow(ctx context.Context, sessionId string, screenId string, windowId string, editMap map[string]interface{}) (*ScreenWindowType, error) {
|
func UpdateScreen(ctx context.Context, screenId string, editMap map[string]interface{}) (*ScreenType, error) {
|
||||||
var rtn *ScreenWindowType
|
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||||
query := `SELECT sessionid FROM screen_window WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
query := `SELECT screenid FROM screen WHERE screenid = ?`
|
||||||
if !tx.Exists(query, sessionId, screenId, windowId) {
|
if !tx.Exists(query, screenId) {
|
||||||
return fmt.Errorf("screen-window not found")
|
return fmt.Errorf("screen not found")
|
||||||
}
|
}
|
||||||
if anchorLine, found := editMap[SWField_AnchorLine]; found {
|
if anchorLine, found := editMap[ScreenField_AnchorLine]; found {
|
||||||
query = `UPDATE screen_window SET anchor = json_set(anchor, '$.anchorline', ?) WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
query = `UPDATE screen SET anchor = json_set(anchor, '$.anchorline', ?) WHERE screenid = ?`
|
||||||
tx.Exec(query, anchorLine, sessionId, screenId, windowId)
|
tx.Exec(query, anchorLine, screenId)
|
||||||
}
|
}
|
||||||
if anchorOffset, found := editMap[SWField_AnchorOffset]; found {
|
if anchorOffset, found := editMap[ScreenField_AnchorOffset]; found {
|
||||||
query = `UPDATE screen_window SET anchor = json_set(anchor, '$.anchoroffset', ?) WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
query = `UPDATE screen SET anchor = json_set(anchor, '$.anchoroffset', ?) WHERE screenid = ?`
|
||||||
tx.Exec(query, anchorOffset, sessionId, screenId, windowId)
|
tx.Exec(query, anchorOffset, screenId)
|
||||||
}
|
}
|
||||||
if sline, found := editMap[SWField_SelectedLine]; found {
|
if sline, found := editMap[ScreenField_SelectedLine]; found {
|
||||||
query = `UPDATE screen_window SET selectedline = ? WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
query = `UPDATE screen SET selectedline = ? WHERE screenid = ?`
|
||||||
tx.Exec(query, sline, sessionId, screenId, windowId)
|
tx.Exec(query, sline, screenId)
|
||||||
}
|
}
|
||||||
if focusType, found := editMap[SWField_Focus]; found {
|
if focusType, found := editMap[ScreenField_Focus]; found {
|
||||||
query = `UPDATE screen_window SET focustype = ? WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
query = `UPDATE screen SET focustype = ? WHERE screenid = ?`
|
||||||
tx.Exec(query, focusType, sessionId, screenId, windowId)
|
tx.Exec(query, focusType, screenId)
|
||||||
}
|
}
|
||||||
var sw ScreenWindowType
|
if tabColor, found := editMap[ScreenField_TabColor]; found {
|
||||||
query = `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
query = `UPDATE screen SET screenopts = json_set(screenopts, '$.tabcolor', ?) WHERE screenid = ?`
|
||||||
found := tx.Get(&sw, query, sessionId, screenId, windowId)
|
tx.Exec(query, tabColor, screenId)
|
||||||
if found {
|
}
|
||||||
rtn = &sw
|
if pterm, found := editMap[ScreenField_PTerm]; found {
|
||||||
|
query = `UPDATE screen SET screenopts = json_set(screenopts, '$.pterm', ?) WHERE screenid = ?`
|
||||||
|
tx.Exec(query, pterm, screenId)
|
||||||
|
}
|
||||||
|
if name, found := editMap[ScreenField_Name]; found {
|
||||||
|
query = `UPDATE screen SET name = ? WHERE screenid = ?`
|
||||||
|
tx.Exec(query, name, screenId)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if txErr != nil {
|
if txErr != nil {
|
||||||
return nil, txErr
|
return nil, txErr
|
||||||
}
|
}
|
||||||
return rtn, nil
|
return GetScreenById(ctx, screenId)
|
||||||
}
|
|
||||||
|
|
||||||
func GetScreenWindowByIds(ctx context.Context, sessionId string, screenId string, windowId string) (*ScreenWindowType, error) {
|
|
||||||
var rtn *ScreenWindowType
|
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
||||||
var sw ScreenWindowType
|
|
||||||
query := `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ? AND windowid = ?`
|
|
||||||
found := tx.Get(&sw, query, sessionId, screenId, windowId)
|
|
||||||
if found {
|
|
||||||
rtn = &sw
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if txErr != nil {
|
|
||||||
return nil, txErr
|
|
||||||
}
|
|
||||||
return rtn, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLineResolveItems(ctx context.Context, sessionId string, windowId string) ([]ResolveItem, error) {
|
func GetLineResolveItems(ctx context.Context, sessionId string, windowId string) ([]ResolveItem, error) {
|
||||||
@ -1766,33 +1708,32 @@ func GetLineResolveItems(ctx context.Context, sessionId string, windowId string)
|
|||||||
return rtn, nil
|
return rtn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateSWsWithCmdFg(ctx context.Context, sessionId string, cmdId string) ([]*ScreenWindowType, error) {
|
func UpdateScreensWithCmdFg(ctx context.Context, sessionId string, cmdId string) ([]*ScreenType, error) {
|
||||||
var rtn []*ScreenWindowType
|
var rtn []*ScreenType
|
||||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||||
query := `SELECT sessionid, screenid, windowid
|
query := `SELECT screenid
|
||||||
FROM screen_window sw
|
FROM screen s
|
||||||
WHERE
|
WHERE
|
||||||
sessionid = ?
|
s.sessionid = ?
|
||||||
AND focustype = 'cmd-fg'
|
AND s.focustype = 'cmd-fg'
|
||||||
AND selectedline IN (SELECT linenum
|
AND s.selectedline IN (SELECT linenum
|
||||||
FROM line l
|
FROM line l
|
||||||
WHERE l.sessionid = sw.sessionid
|
WHERE l.sessionid = s.sessionid
|
||||||
AND l.windowid = sw.windowid
|
AND l.windowid = s.windowid
|
||||||
AND l.cmdid = ?
|
AND l.cmdid = ?
|
||||||
)`
|
)`
|
||||||
var swKeys []SWKey
|
screenIds := tx.SelectStrings(query, sessionId, cmdId)
|
||||||
tx.Select(&swKeys, query, sessionId, cmdId)
|
if len(screenIds) == 0 {
|
||||||
if len(swKeys) == 0 {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, key := range swKeys {
|
for _, screenId := range screenIds {
|
||||||
editMap := make(map[string]interface{})
|
editMap := make(map[string]interface{})
|
||||||
editMap[SWField_Focus] = SWFocusInput
|
editMap[ScreenField_Focus] = ScreenFocusInput
|
||||||
sw, err := UpdateScreenWindow(tx.Context(), key.SessionId, key.ScreenId, key.WindowId, editMap)
|
screen, err := UpdateScreen(tx.Context(), screenId, editMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rtn = append(rtn, sw)
|
rtn = append(rtn, screen)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
"github.com/golang-migrate/migrate/v4"
|
"github.com/golang-migrate/migrate/v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxMigration = 8
|
const MaxMigration = 9
|
||||||
const MigratePrimaryScreenVersion = 9
|
const MigratePrimaryScreenVersion = 9
|
||||||
|
|
||||||
func MakeMigrate() (*migrate.Migrate, error) {
|
func MakeMigrate() (*migrate.Migrate, error) {
|
||||||
|
@ -73,9 +73,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SWFocusInput = "input"
|
ScreenFocusInput = "input"
|
||||||
SWFocusCmd = "cmd"
|
ScreenFocusCmd = "cmd"
|
||||||
SWFocusCmdFg = "cmd-fg"
|
ScreenFocusCmdFg = "cmd-fg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const MaxTzNameLen = 50
|
const MaxTzNameLen = 50
|
||||||
@ -276,29 +276,6 @@ type SessionStatsType struct {
|
|||||||
DiskStats SessionDiskSizeType `json:"diskstats"`
|
DiskStats SessionDiskSizeType `json:"diskstats"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WindowOptsType struct {
|
|
||||||
PTerm string `json:"pterm,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (opts *WindowOptsType) Scan(val interface{}) error {
|
|
||||||
return quickScanJson(opts, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (opts WindowOptsType) Value() (driver.Value, error) {
|
|
||||||
return quickValueJson(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
type WindowShareOptsType struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (opts *WindowShareOptsType) Scan(val interface{}) error {
|
|
||||||
return quickScanJson(opts, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (opts WindowShareOptsType) Value() (driver.Value, error) {
|
|
||||||
return quickValueJson(opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
var RemoteNameRe = regexp.MustCompile("^\\*?[a-zA-Z0-9_-]+$")
|
var RemoteNameRe = regexp.MustCompile("^\\*?[a-zA-Z0-9_-]+$")
|
||||||
|
|
||||||
type RemotePtrType struct {
|
type RemotePtrType struct {
|
||||||
@ -361,51 +338,6 @@ func (r RemotePtrType) MakeFullRemoteRef() string {
|
|||||||
return fmt.Sprintf("@%s:%s:%s", r.OwnerId, r.RemoteId, r.Name)
|
return fmt.Sprintf("@%s:%s:%s", r.OwnerId, r.RemoteId, r.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
type WindowType struct {
|
|
||||||
SessionId string `json:"sessionid"`
|
|
||||||
WindowId string `json:"windowid"`
|
|
||||||
CurRemote RemotePtrType `json:"curremote"`
|
|
||||||
WinOpts WindowOptsType `json:"winopts"`
|
|
||||||
OwnerId string `json:"ownerid"`
|
|
||||||
NextLineNum int64 `json:"nextlinenum"`
|
|
||||||
ShareMode string `json:"sharemode"`
|
|
||||||
ShareOpts WindowShareOptsType `json:"shareopts"`
|
|
||||||
Lines []*LineType `json:"lines"`
|
|
||||||
Cmds []*CmdType `json:"cmds"`
|
|
||||||
|
|
||||||
// only for updates
|
|
||||||
Remove bool `json:"remove,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WindowType) ToMap() map[string]interface{} {
|
|
||||||
rtn := make(map[string]interface{})
|
|
||||||
rtn["sessionid"] = w.SessionId
|
|
||||||
rtn["windowid"] = w.WindowId
|
|
||||||
rtn["curremoteownerid"] = w.CurRemote.OwnerId
|
|
||||||
rtn["curremoteid"] = w.CurRemote.RemoteId
|
|
||||||
rtn["curremotename"] = w.CurRemote.Name
|
|
||||||
rtn["nextlinenum"] = w.NextLineNum
|
|
||||||
rtn["winopts"] = quickJson(w.WinOpts)
|
|
||||||
rtn["ownerid"] = w.OwnerId
|
|
||||||
rtn["sharemode"] = w.ShareMode
|
|
||||||
rtn["shareopts"] = quickJson(w.ShareOpts)
|
|
||||||
return rtn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WindowType) FromMap(m map[string]interface{}) bool {
|
|
||||||
quickSetStr(&w.SessionId, m, "sessionid")
|
|
||||||
quickSetStr(&w.WindowId, m, "windowid")
|
|
||||||
quickSetStr(&w.CurRemote.OwnerId, m, "curremoteownerid")
|
|
||||||
quickSetStr(&w.CurRemote.RemoteId, m, "curremoteid")
|
|
||||||
quickSetStr(&w.CurRemote.Name, m, "curremotename")
|
|
||||||
quickSetInt64(&w.NextLineNum, m, "nextlinenum")
|
|
||||||
quickSetJson(&w.WinOpts, m, "winopts")
|
|
||||||
quickSetStr(&w.OwnerId, m, "ownerid")
|
|
||||||
quickSetStr(&w.ShareMode, m, "sharemode")
|
|
||||||
quickSetJson(&w.ShareOpts, m, "shareopts")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HistoryItemType) ToMap() map[string]interface{} {
|
func (h *HistoryItemType) ToMap() map[string]interface{} {
|
||||||
rtn := make(map[string]interface{})
|
rtn := make(map[string]interface{})
|
||||||
rtn["historyid"] = h.HistoryId
|
rtn["historyid"] = h.HistoryId
|
||||||
@ -448,35 +380,83 @@ func (h *HistoryItemType) FromMap(m map[string]interface{}) bool {
|
|||||||
|
|
||||||
type ScreenOptsType struct {
|
type ScreenOptsType struct {
|
||||||
TabColor string `json:"tabcolor,omitempty"`
|
TabColor string `json:"tabcolor,omitempty"`
|
||||||
|
PTerm string `json:"pterm,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts *ScreenOptsType) Scan(val interface{}) error {
|
type SWKeys struct {
|
||||||
return quickScanJson(opts, val)
|
SessionId string
|
||||||
}
|
WindowId string
|
||||||
|
|
||||||
func (opts ScreenOptsType) Value() (driver.Value, error) {
|
|
||||||
return quickValueJson(opts)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScreenType struct {
|
type ScreenType struct {
|
||||||
SessionId string `json:"sessionid"`
|
SessionId string `json:"sessionid"`
|
||||||
ScreenId string `json:"screenid"`
|
ScreenId string `json:"screenid"`
|
||||||
ScreenIdx int64 `json:"screenidx"`
|
WindowId string `json:"windowid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ActiveWindowId string `json:"activewindowid"`
|
ScreenIdx int64 `json:"screenidx"`
|
||||||
ScreenOpts *ScreenOptsType `json:"screenopts"`
|
ScreenOpts ScreenOptsType `json:"screenopts"`
|
||||||
OwnerId string `json:"ownerid"`
|
OwnerId string `json:"ownerid"`
|
||||||
ShareMode string `json:"sharemode"`
|
ShareMode string `json:"sharemode"`
|
||||||
Incognito bool `json:"incognito,omitempty"`
|
CurRemote RemotePtrType `json:"curremote"`
|
||||||
Archived bool `json:"archived,omitempty"`
|
NextLineNum int64 `json:"nextlinenum"`
|
||||||
ArchivedTs int64 `json:"archivedts,omitempty"`
|
SelectedLine int64 `json:"selectedline"`
|
||||||
Windows []*ScreenWindowType `json:"windows"`
|
Anchor ScreenAnchorType `json:"anchor"`
|
||||||
|
FocusType string `json:"focustype"`
|
||||||
|
Archived bool `json:"archived,omitempty"`
|
||||||
|
ArchivedTs int64 `json:"archivedts,omitempty"`
|
||||||
|
|
||||||
|
// only for "full"
|
||||||
|
Lines []*LineType `json:"lines"`
|
||||||
|
Cmds []*CmdType `json:"cmds"`
|
||||||
|
|
||||||
// only for updates
|
// only for updates
|
||||||
Remove bool `json:"remove,omitempty"`
|
Remove bool `json:"remove,omitempty"`
|
||||||
Full bool `json:"full,omitempty"`
|
Full bool `json:"full,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ScreenType) ToMap() map[string]interface{} {
|
||||||
|
rtn := make(map[string]interface{})
|
||||||
|
rtn["sessionid"] = s.SessionId
|
||||||
|
rtn["screenid"] = s.ScreenId
|
||||||
|
rtn["windowid"] = s.WindowId
|
||||||
|
rtn["name"] = s.Name
|
||||||
|
rtn["screenidx"] = s.ScreenIdx
|
||||||
|
rtn["screenopts"] = quickJson(s.ScreenOpts)
|
||||||
|
rtn["ownerid"] = s.OwnerId
|
||||||
|
rtn["sharemode"] = s.ShareMode
|
||||||
|
rtn["curremoteownerid"] = s.CurRemote.OwnerId
|
||||||
|
rtn["curremoteid"] = s.CurRemote.RemoteId
|
||||||
|
rtn["curremotename"] = s.CurRemote.Name
|
||||||
|
rtn["nextlinenum"] = s.NextLineNum
|
||||||
|
rtn["selectedline"] = s.SelectedLine
|
||||||
|
rtn["anchor"] = quickJson(s.Anchor)
|
||||||
|
rtn["focustype"] = s.FocusType
|
||||||
|
rtn["archived"] = s.Archived
|
||||||
|
rtn["archivedts"] = s.ArchivedTs
|
||||||
|
return rtn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ScreenType) FromMap(m map[string]interface{}) bool {
|
||||||
|
quickSetStr(&s.SessionId, m, "sessionid")
|
||||||
|
quickSetStr(&s.ScreenId, m, "screenid")
|
||||||
|
quickSetStr(&s.WindowId, m, "windowid")
|
||||||
|
quickSetStr(&s.Name, m, "name")
|
||||||
|
quickSetInt64(&s.ScreenIdx, m, "screenidx")
|
||||||
|
quickSetJson(&s.ScreenOpts, m, "screenopts")
|
||||||
|
quickSetStr(&s.OwnerId, m, "ownerid")
|
||||||
|
quickSetStr(&s.ShareMode, m, "sharemode")
|
||||||
|
quickSetStr(&s.CurRemote.OwnerId, m, "curremoteownerid")
|
||||||
|
quickSetStr(&s.CurRemote.RemoteId, m, "curremoteid")
|
||||||
|
quickSetStr(&s.CurRemote.Name, m, "curremotename")
|
||||||
|
quickSetInt64(&s.NextLineNum, m, "nextlinenum")
|
||||||
|
quickSetInt64(&s.SelectedLine, m, "selectedline")
|
||||||
|
quickSetJson(&s.Anchor, m, "anchor")
|
||||||
|
quickSetStr(&s.FocusType, m, "focustype")
|
||||||
|
quickSetBool(&s.Archived, m, "archived")
|
||||||
|
quickSetInt64(&s.ArchivedTs, m, "archivedts")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
LayoutFull = "full"
|
LayoutFull = "full"
|
||||||
)
|
)
|
||||||
@ -502,39 +482,11 @@ func (l LayoutType) Value() (driver.Value, error) {
|
|||||||
return quickValueJson(l)
|
return quickValueJson(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SWAnchorType struct {
|
type ScreenAnchorType struct {
|
||||||
AnchorLine int `json:"anchorline,omitempty"`
|
AnchorLine int `json:"anchorline,omitempty"`
|
||||||
AnchorOffset int `json:"anchoroffset,omitempty"`
|
AnchorOffset int `json:"anchoroffset,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *SWAnchorType) Scan(val interface{}) error {
|
|
||||||
return quickScanJson(a, val)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a SWAnchorType) Value() (driver.Value, error) {
|
|
||||||
return quickValueJson(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SWKey struct {
|
|
||||||
SessionId string
|
|
||||||
ScreenId string
|
|
||||||
WindowId string
|
|
||||||
}
|
|
||||||
|
|
||||||
type ScreenWindowType struct {
|
|
||||||
SessionId string `json:"sessionid"`
|
|
||||||
ScreenId string `json:"screenid"`
|
|
||||||
WindowId string `json:"windowid"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Layout LayoutType `json:"layout"`
|
|
||||||
SelectedLine int `json:"selectedline"`
|
|
||||||
Anchor SWAnchorType `json:"anchor"`
|
|
||||||
FocusType string `json:"focustype"`
|
|
||||||
|
|
||||||
// only for updates
|
|
||||||
Remove bool `json:"remove,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HistoryItemType struct {
|
type HistoryItemType struct {
|
||||||
HistoryId string `json:"historyid"`
|
HistoryId string `json:"historyid"`
|
||||||
Ts int64 `json:"ts"`
|
Ts int64 `json:"ts"`
|
||||||
|
@ -30,24 +30,23 @@ func (PtyDataUpdate) UpdateType() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ModelUpdate struct {
|
type ModelUpdate struct {
|
||||||
Sessions []*SessionType `json:"sessions,omitempty"`
|
Sessions []*SessionType `json:"sessions,omitempty"`
|
||||||
ActiveSessionId string `json:"activesessionid,omitempty"`
|
ActiveSessionId string `json:"activesessionid,omitempty"`
|
||||||
Windows []*WindowType `json:"windows,omitempty"`
|
Screens []*ScreenType `json:"screens,omitempty"`
|
||||||
ScreenWindows []*ScreenWindowType `json:"screenwindows,omitempty"`
|
Line *LineType `json:"line,omitempty"`
|
||||||
Line *LineType `json:"line,omitempty"`
|
Lines []*LineType `json:"lines,omitempty"`
|
||||||
Lines []*LineType `json:"lines,omitempty"`
|
Cmd *CmdType `json:"cmd,omitempty"`
|
||||||
Cmd *CmdType `json:"cmd,omitempty"`
|
CmdLine *CmdLineType `json:"cmdline,omitempty"`
|
||||||
CmdLine *CmdLineType `json:"cmdline,omitempty"`
|
Info *InfoMsgType `json:"info,omitempty"`
|
||||||
Info *InfoMsgType `json:"info,omitempty"`
|
ClearInfo bool `json:"clearinfo,omitempty"`
|
||||||
ClearInfo bool `json:"clearinfo,omitempty"`
|
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
|
||||||
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
|
History *HistoryInfoType `json:"history,omitempty"`
|
||||||
History *HistoryInfoType `json:"history,omitempty"`
|
Interactive bool `json:"interactive"`
|
||||||
Interactive bool `json:"interactive"`
|
Connect bool `json:"connect,omitempty"`
|
||||||
Connect bool `json:"connect,omitempty"`
|
MainView string `json:"mainview,omitempty"`
|
||||||
MainView string `json:"mainview,omitempty"`
|
Bookmarks []*BookmarkType `json:"bookmarks,omitempty"`
|
||||||
Bookmarks []*BookmarkType `json:"bookmarks,omitempty"`
|
HistoryViewData *HistoryViewData `json:"historyviewdata,omitempty"`
|
||||||
HistoryViewData *HistoryViewData `json:"historyviewdata,omitempty"`
|
ClientData *ClientData `json:"clientdata,omitempty"`
|
||||||
ClientData *ClientData `json:"clientdata,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ModelUpdate) UpdateType() string {
|
func (ModelUpdate) UpdateType() string {
|
||||||
|
Loading…
Reference in New Issue
Block a user