diff --git a/app/graffiti.go b/app/graffiti.go new file mode 100644 index 0000000..0cac3a2 --- /dev/null +++ b/app/graffiti.go @@ -0,0 +1,95 @@ +package app + +import ( + "os" + "os/exec" + "path" + "strings" + "time" + + "git.sr.ht/~rockorager/vaxis" + "git.sr.ht/~rockorager/vaxis/widgets/term" + "git.tilde.town/nbsp/neofeels/ttbp" + "git.tilde.town/nbsp/neofeels/ui" +) + +type Graffiti struct { + title string + content string + help string +} + +func NewGraffiti() *Posted { + var content string + if ttbp.GraffitiFree() { + content = `the graffiti wall is a world-writeable text file. anyone can scribble on it; +anyone can move or delete things. please be considerate of your neighbors when +writing on it. + +no one will be able to visit the wall while you are here, so don't worry about +overwriting someone else's work. anything you do to the wall will be recorded if +you save the file, and you can cancel your changes by exiting without saving.` + } else { + content = "sorry, but someone's there right now. try again in a few!" + } + return &Posted{ + title, + content, + "↵ enter q return", + } +} + +func (graffiti *Graffiti) Event(state *ui.State, event vaxis.Event) (processed bool) { + if key, ok := event.(vaxis.Key); ok && key.EventType == vaxis.EventPress { + switch key.String() { + case "Ctrl+c", "Ctrl+d": + close(ui.Quit) + case "q", "h", "Left": + ui.ViewChange <- NewMainMenu() + case "Enter", "l", "Right": + if ttbp.GraffitiFree() { + os.Create(ttbp.PathWallLock) + editGraffiti(state) + os.Remove(ttbp.PathWallLock) + } + ui.ViewChange <- NewMainMenu() + } + processed = true + } + win := state.Window() + win.New(win.Width/2-10, win.Height/2-8, 20, 5).Print(vaxis.Segment{Text: graffiti.title}) + win.New(win.Width/2-21, win.Height/2-2, 43, 9).Print(vaxis.Segment{Text: graffiti.content}) + win.New(win.Width/2-9, win.Height/2+8, 18, 1).Print(vaxis.Segment{Text: graffiti.help}) + return +} + +func editGraffiti(state *ui.State) { + state.HideCursor() + vt := term.New() + vt.TERM = os.Getenv("TERM") + vt.Attach(state.PostEvent()) + vt.Focus() + err := vt.Start(exec.Command(os.ExpandEnv(os.Getenv("EDITOR")), ttbp.PathWall)) + if err != nil { + panic(err) + } + defer vt.Close() + + for ev := range state.Events() { + switch ev.(type) { + case term.EventClosed: + state.HideCursor() + state.Window().Clear() + return + case vaxis.Redraw: + vt.Draw(state.Window()) + state.Render() + continue + } + + // for some reason vaxis doubles all events for Press/Release so this just ignores releases + if key, ok := ev.(vaxis.Key); ok && key.EventType == vaxis.EventPress { + vt.Update(ev) + } + } +} diff --git a/app/menu.go b/app/menu.go index 0655526..d449462 100644 --- a/app/menu.go +++ b/app/menu.go @@ -34,7 +34,7 @@ func NewMainMenu() *MainMenu { "check out your neighbors", "browse global feels", "visit your subscriptions", - "scribble some graffiti", // TODO + "scribble some graffiti", "change your settings", "see credits", "read documentation", @@ -71,6 +71,8 @@ func (menu *MainMenu) Event(state *ui.State, event vaxis.Event) (processed bool) ui.ViewChange <- NewBrowse() case 4: ui.ViewChange <- NewSubscriptions() + case 5: + ui.ViewChange <- NewGraffiti() case 6: ui.ViewChange <- NewConfig() case 7: diff --git a/main.go b/main.go index bd092a8..ab94c50 100644 --- a/main.go +++ b/main.go @@ -47,6 +47,7 @@ press ↵ to set up an account, or Ctrl+c to quit. you can always come back late os.WriteFile(path.Join(ttbp.PathUserConfig, "footer.txt"), footer, 0644) os.WriteFile(path.Join(ttbp.PathUserConfig, "style.css"), style, 0644) config.Default.Write() + // TODO: edit users.txt } func main() { diff --git a/ttbp/ttbp.go b/ttbp/ttbp.go index 3ad6274..0172e44 100644 --- a/ttbp/ttbp.go +++ b/ttbp/ttbp.go @@ -331,3 +331,8 @@ func writeEntry(post Post) string { buf.String(), dateString, ) } + +func GraffitiFree() bool { + _, err := os.Stat(PathWallLock) + return os.IsNotExist(err) +}