aboutsummaryrefslogtreecommitdiff
path: root/go-src/windowsHelpers.go
blob: 9b1d2d992661b2b0d9664f7c97aba1bd6e11d5d8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package ctfc

import (
	"strings"
	"time"

	"gitlab.com/Syndamia/ctfc/go-src/csi"
	"gitlab.com/Syndamia/ctfc/go-src/ui"
	"gitlab.com/Syndamia/ctfc/go-src/utils"
)

/* Pagination */

const pageSize = 15

func totalPages(messageAmount int) int {
	return utils.CeilDivInt(messageAmount, pageSize)
}

func paginate(page int, messages ...string) []string {
	return messages[utils.MaxInt(len(messages)-pageSize*page, 0) : len(messages)-pageSize*(page-1)]
}

// Must be run in a routine ( go routinePaginatedSubwindow(...) )
// There must be empty lines for the subwindow
func routinePaginatedSubwindow(messages *[]string, updateMessages func(*[]string), lastLine *int, page int, customLinesBelow int, numbered bool) {
	for *lastLine > -2 {
		// Update messages, if we've already shown the last message
		if *lastLine == len(*messages)-1 {
			updateMessages(messages)
			continue
		}

		*lastLine = len(*messages) - 1
		csi.SaveCursorPosition()

		csi.MoveCursorUpN(pageSize + 1 + customLinesBelow)
		csi.MoveCursorToBeginningOfLine()

		pageMessages := paginate(page, *messages...)

		// Leaves empty lines at the top, if there aren't enough messages to fill a full page
		// Works on the assumption that there are ui.EmptyLine(), where messages would be printed
		for i := 0; i < pageSize-len(pageMessages); i++ {
			csi.MoveCursorDown()
		}

		if numbered {
			ui.NumberedFields(pageMessages...)
		} else {
			ui.TextFields(pageMessages...)
		}

		ui.PageField(page, totalPages(len(*messages)))

		csi.RestoreCursorPosition()
		time.Sleep(500 * time.Millisecond)
	}
}

func initPaginatedValues(defaultLength int, values *[]string) {
	if len(*values) == defaultLength {
		*values = append(append(*values, "."), "")
	}
}

/* Input actions */

type inputAction struct {
	value   string
	execute window
	args    []string
}

func handleInputActions(input string, handleNav bool, ia ...inputAction) func() {
	if handleNav {
		ia = append(ia,
			inputAction{"C", chatsWindow, nil},
			inputAction{"D", directMessagesWindow, nil},
			inputAction{"A", accountWindow, nil},
			inputAction{"L", logoutWindow, nil},
		)
	}
	for _, v := range ia {
		if strings.ToLower(input) == strings.ToLower(v.value) {
			return func() { v.execute(v.args...) }
		}
	}
	return nil
}

/* Form */

type formInput struct {
	name           string
	specification  string
	validationFunc func(string) bool
}

func formWindow(boxTitle string, backWindow window, formInputs []formInput, currentValues ...string) (userInputs []string) {
	userInputs = currentValues
	// Go through all inputs
	for i, v := range formInputs[len(currentValues):] {
		csi.ClearScreen()

		ui.NormalBox(true, boxTitle)

		// Show filled input fields
		for j, va := range userInputs {
			ui.InputFieldFilled(formInputs[j].name, va)
		}

		// Wait for input on current input field
		input := ui.InputField(v.name + v.specification)

		// Go to the "backWindow", if we're on the first input, we are given a back window, and the letter B is given
		if i == 0 && backWindow != nil && strings.ToLower(input) == "b" {
			defer backWindow()
			return
		}

		// If we're validating input data, try to validate
		if v.validationFunc != nil {
			// If input data isn't valid, show an error and the same screen
			if !v.validationFunc(input) {
				formCallback := func(...string) {
					defer formWindow(boxTitle, backWindow, formInputs, userInputs...)
				}
				defer showError(invalidValueFor(v.name), formCallback)
				return
			}
		}

		// Add current input as a filled input
		userInputs = append(userInputs, input)
	}
	return
}

/* Error */

func showError(message string, callback window, callbackData ...string) {
	csi.ClearScreen()

	ui.ErrorBox(message)
	csi.BlockClearScreenNextTime()

	defer callback(callbackData...)
}